Infinite Scroll -> Load more posts as the reader scrolls downNo error
Recoverable fatal error: Object of class Closure could not be converted to string in /var/www/html/wp-content/plugins/jetpack/modules/infinite-scroll/infinity.php on line 1763
There has been a critical error on your website.
Jetpack: 9.0.2
AMP: 2.0.4
Load more posts in page with a button the same error.
Thanks for the report. Could you let me know what theme you experienced this with?
Theme based on https://github.com/automattic/_s
/**
* Add theme support for infinite scroll.
*
* @link https://jetpack.com/support/infinite-scroll/
*/
add_theme_support( 'infinite-scroll', array(
'type' => 'click',
'wrapper' => false,
'render' => function () {
while ( have_posts() ) {
the_post();
get_template_part( 'template-parts/content', 'blog' );
}
},
) );
Is your theme available for download, so I can give it a quick test?
Thanks!
It isn't available but it doesn't have a big differences with _s
I've tried reproducing with a new theme built off _s, but I've had no luck.
Do you have any additional Infinite Scroll customizations in place, using filters such as infinite_scroll_settings maybe?
@jeherve: The problem here is a combination of two things.
The code quoted in https://github.com/Automattic/jetpack/issues/17461#issuecomment-707222366 is setting the 'render' property to a Closure. That seems ok as far as the documentation for the 'render' property goes: it calls for a "function", and that's what it's getting.
In The_Neverending_Home_Page::amp_load_hooks(), the code is assuming the 'render' function is a string, or is stringifyable:
$template = self::get_settings()->render;
// ...
if ( is_callable( "amp_{$template}_hooks" ) ) { // ← line 1763
call_user_func( "amp_{$template}_hooks" );
}
That fails when 'render' is closure. It'll also fail for an array callable (e.g. array( 'ClassName', 'method' ) or array( $obj, 'method' )). It may also fail more subtly for a string referencing a class static method (e.g. ClassName::method) rather than a global function, as the theme would have to do some particularly weird stuff to define the amp hooks function in a way that it'll actually be called.
Also of note is that the code will try calling amp__hooks() if the theme didn't provide a render function at all, which is probably also not intended.
As for what we might do here, I see two options.
get_settings() to reject any non-string and any string containing :: for 'render' (and 'footer_callback'). That will break any themes that are using some other kind of callable explicitly and immediately, instead of only doing so if used in conjunction with the AMP plugin.::.I see the AMP code was added in #16048 by @pereirinha, maybe they can provide further insight here.
2. In
The_Neverending_Home_Page::amp_load_hooks(), the code is assuming the 'render' function is a string, or is stringifyable:
I just came across this myself. To me this seems like a strange way to implement extensibility. Shouldn't there rather be an action like:
do_action( 'jetpack_initialize_infinite_scroll' );
Then instead of the theme compatibility doing this:
It could instead do:
add_action( 'jetpack_initialize_infinite_scroll', function() {
add_filter( 'jetpack_amp_infinite_footers', 'twentynineteen_amp_infinite_footers', 10, 2 );
add_filter( 'jetpack_amp_infinite_output', 'twentynineteen_amp_infinite_output' );
add_filter( 'jetpack_amp_infinite_older_posts', 'twentynineteen_amp_infinite_older_posts' );
} );
Or rather, why not just:
add_filter( 'jetpack_amp_infinite_footers', 'twentynineteen_amp_infinite_footers', 10, 2 );
add_filter( 'jetpack_amp_infinite_output', 'twentynineteen_amp_infinite_output' );
add_filter( 'jetpack_amp_infinite_older_posts', 'twentynineteen_amp_infinite_older_posts' );
Why the indirection?
Thanks all for the inputs on this.
I'll revise the comments and do some testing, but my first impression is that @westonruter suggestion of having do_action( 'jetpack_initialize_infinite_scroll' ); seems to be the best path.
I'll update this issue as soon as possible.
I also have started a PR with what I believe is an improved approach to implementing infinite scroll in AMP: https://github.com/Automattic/jetpack/pull/17497.
Most helpful comment
@jeherve: The problem here is a combination of two things.
The code quoted in https://github.com/Automattic/jetpack/issues/17461#issuecomment-707222366 is setting the 'render' property to a Closure. That seems ok as far as the documentation for the 'render' property goes: it calls for a "function", and that's what it's getting.
In
The_Neverending_Home_Page::amp_load_hooks(), the code is assuming the 'render' function is a string, or is stringifyable:That fails when 'render' is closure. It'll also fail for an array callable (e.g.
array( 'ClassName', 'method' )orarray( $obj, 'method' )). It may also fail more subtly for a string referencing a class static method (e.g.ClassName::method) rather than a global function, as the theme would have to do some particularly weird stuff to define the amp hooks function in a way that it'll actually be called.Also of note is that the code will try calling
amp__hooks()if the theme didn't provide a render function at all, which is probably also not intended.As for what we might do here, I see two options.
get_settings()to reject any non-string and any string containing::for 'render' (and 'footer_callback'). That will break any themes that are using some other kind of callable explicitly and immediately, instead of only doing so if used in conjunction with the AMP plugin.::.I see the AMP code was added in #16048 by @pereirinha, maybe they can provide further insight here.