Make WordPress Core

Opened 10 years ago

Closed 4 years ago

#29204 closed defect (bug) (fixed)

SimplePie non-static WP_Feed_Cache::create error in fetch_feed()

Reported by: usestrict's profile useStrict Owned by: sergeybiryukov's profile SergeyBiryukov
Milestone: 5.6 Priority: normal
Severity: normal Version: 3.8
Component: Feeds Keywords: has-patch commit
Focuses: Cc:

Description

There seems to be a bug in SimplePie that raises the following notice every time an RSS Feed Dashboard widget is added to the Dashboard.

call_user_func_array() expects parameter 1 to be a valid callback, non-static method WP_Feed_Cache::create() should not be called statically on line 215 in file /path/to/wp-includes/SimplePie/Registry.php

Calling fetch_feed() is the best way to raise it. I'm using 'blackbox-debug-bar' plugin to capture the notices.

Examples to reproduce the error:

Install and use Dashboard Feed Widget

or follow one of the tuts below.

http://adamscottcreative.com/add-your-own-news-feed-to-wordpress-dashboard/

http://samglover.net/build-your-own-wordpress-dashboard-widget-for-any-rss-feed/

I suspect the reason we don't see it when "WordPress News" is displayed is because the fetch_feed() runs via ajax and does not get captured in the current screen.

Attachments (7)

29204.patch (579 bytes) - added by Senning 10 years ago.
Fix WP_Feed_Cache::create being non-static
29204.diff (1.6 KB) - added by dd32 10 years ago.
29204.2.diff (1.6 KB) - added by markoheijnen 8 years ago.
0001-29204-Fix-errors-about-non-static-WP_Feed_Cache-crea.patch (1.3 KB) - added by ComputerGuru 7 years ago.
Updated patch for error
0001-29204-Fix-errors-about-non-static-WP_Feed_Cache-crea.2.patch (2.1 KB) - added by ComputerGuru 7 years ago.
Updated patch and validated against trunk.
29204.3.diff (1.3 KB) - added by afragen 4 years ago.
Combine patches from @dd32 and @ComputerGuru
29204.4.diff (1.8 KB) - added by SergeyBiryukov 4 years ago.

Download all attachments as: .zip

Change History (65)

#1 @Ipstenu
10 years ago

  • Version changed from trunk to 3.8

Using normal debug bar and wp_debug set to true, I don't have any errors on my site. I can reproduce the error with blackbox-debug-bar, however it shows on also 3.9.2 as well so this isn't 'new'

3.8 https://wordpress.org/support/topic/custom-dashboard-rss-feed-strict-error?replies=2

Looking at SimplePie, this may just be to support older versions of PHP: https://github.com/simplepie/simplepie/blob/master/library/SimplePie/Registry.php#L210

#2 @Senning
10 years ago

I'm getting the same error, and adding the static keyword to WP_Feed_Cache::create fixes it.

Going by the DocBlock (and SimplePie_Cache::create, which it extends), it looks like it's supposed to be static anyway.

@Senning
10 years ago

Fix WP_Feed_Cache::create being non-static

This ticket was mentioned in Slack in #core by dd32. View the logs.


10 years ago

#4 @dd32
10 years ago

Adding the static keyword might first seem right, but the upstream method isn't marked as a static, so doing so will cause PHP Fatal error: Cannot make non static method SimplePie_Cache::create() static in class WP_Feed_Cache.

I guess the "best" way to fix this is to use the Registry system SP has. @rmccue is 29204.diff the correct way there?

@dd32
10 years ago

#5 @nacin
10 years ago

Fun history here: [21652], #21183.

#6 follow-up: @l3rady
10 years ago

I would love to see this fixed as currently we are having to mute this error in Sentry every time we add a WP site.

#7 @HoaSi
9 years ago

  • Keywords has-screenshots added

Reproducing the original issue using Bones on local install, PHP7:

https://i.imgur.com/GE2RTOA.png

https://i.imgur.com/NKjWjKL.png

After removing $feed->set_cache_class( 'WP_Feed_Cache' ); currently at line 674 and adding SimplePie_Cache::register( 'wp_transient', 'WP_Feed_Cache_Transient' );
$feed->set_cache_location( 'wp_transient://' . $url );

I can confirm that the patch 29204.diff fixes the issue.

https://i.imgur.com/ypXD4FT.png

Last edited 9 years ago by HoaSi (previous) (diff)

#8 @jdgrimes
8 years ago

#37121 was marked as a duplicate.

@markoheijnen
8 years ago

#9 @markoheijnen
8 years ago

  • Keywords has-patch added

I just created an alternative solution. Could this be something to fix it?

#10 @NathanAtmoz
8 years ago

I'm guessing this is related to this ticket...

When I attempt to use the RSS Widget with PHP7 I get this deprecation notice on pages where the widget is displayed:
Non-static method WP_Feed_Cache::create() should not be called statically

#11 @markoheijnen
8 years ago

@rmccue @ocean90: Any change this can be looked at for 4.6?

This ticket was mentioned in Slack in #core by markoheijnen. View the logs.


8 years ago

#13 @SergeyBiryukov
8 years ago

  • Keywords 4.7-early added

This ticket was mentioned in Slack in #core by helen. View the logs.


8 years ago

#15 @helen
8 years ago

  • Keywords needs-refresh added; has-screenshots removed

#16 @SergeyBiryukov
8 years ago

  • Owner set to SergeyBiryukov
  • Status changed from new to reviewing

#17 @jeremyfelt
8 years ago

#38069 was marked as a duplicate.

#18 @jfoulquier
8 years ago

I also used to get the error since a long time. As far as I can tell, 29204.2.diff from @markoheijnen fixes it.

#19 @thefarlilacfield
8 years ago

I'm writing to confirm that 29204.diff fixes this.

For the sake of reference (search results) it's worth noting a few things.

This change removes WP_Feed_Cache as a dependency of the WordPress core.

The set_cache_class() method that is being removed by the patch had already been depreciated as of the 2012 version of SimplePie (1.3.1) relied upon by WordPress (up to 4.7 at least).

My look at the code has been cursory, but it appears that WordPress is relying upon legacy features of the library that inherently require a dynamic method to be called as static. As of PHP 5 this has merited an an E_STRICT warning. PHP 7 escalates this to an E_DEPRECATED warning, and the current documentation notes that support may be removed in the future.

It also appears that the maintainers of SimplePie have specifically assumed the legacy burden of WordPress support all the way up to version 1.4.3, maintaining backwards compatibility "unless there's a really good reason not to" (mblaney being is the current maintainer), and that this consideration has overshadowed discussion of a 2.0.0 revision of their library.

#20 @austinpray
7 years ago

What's the word on this one?

#21 @Shelob9
7 years ago

I'm plus oneing this ticket. I'm not supposed to, but tired of seeing this in logs.

#23 @subscriptiongroup
7 years ago

@SergeyBiryukov Looking at the error details, the solution proposed at https://core.trac.wordpress.org/attachment/ticket/29204/29204.patch seems valid and really simple.

Is there a reason why this is not merged, yet it's pushed back for the past three(!) years?

Array
(
    [type] => 8192
    [message] => Non-static method WP_Feed_Cache::create() should not be called statically
    [file] => /home/xxxx/public_html/wp-includes/SimplePie/Registry.php
    [line] => 215
)

#24 @ComputerGuru
7 years ago

Is there any work required for this that one could volunteer to do or is it just waiting on WP.org? It's marked as v3.8 and WordPress v4.9 just shipped....

#25 @rogerlos
7 years ago

+1

I've been staring at

Non-static method WP_Feed_Cache::create() should not be called statically
In \wp-includes\SimplePie\Registry.php [line 215]:

on my dashboard for a few years now...

#26 @Mte90
7 years ago

Any chance for a fix soon?
This problem happen with the widget with the wordpress events in the dashboard so fills the error log very often.

Last edited 7 years ago by Mte90 (previous) (diff)

This ticket was mentioned in Slack in #core by mte90. View the logs.


7 years ago

#30 @mopsyd
7 years ago

I'm going to offer up a chunk of functionality from one of my own projects to solve this to whoever is actually working on the ticket, as well as any related tickets. It's a trait that you can drop onto any class that does a performant, intelligent substitution for call_user_func_array(). It's unit tested at 100%, it's faster than call_user_func_array by miles, it handles both static and object calls natively without distinction, and it can be dropped onto any class. Whoever is working on this or any related issues is free to use it for this or any related bugs.

The only thing you need to change in this trait is the exception, which should be converted to a native one instead of one of the ones from the rest of the project this is from (line 97). This project has a custom reporting and error handling system that the custom exception ties into, but that is the only external thing it calls, which can be easily substituted. Other than that it has no other dependencies. It solves all static call bugs like this one if used consistently.

Source: https://bitbucket.org/oroborosframework/oroboros-core/src/9e77876320ff55a4a8d1409839447036603e4f0a/src/core/traits/utilities/core/CallableUtilityTrait.php?at=master&fileviewer=file-view-default

This works by avoiding the underlying overhead of call_user_func_array (which is slooooow), by first blocking non-callables with an exception so they do not generate an error, and then doing a set of matching checks that will handle up to 14 parameters and call the class, array, closure, or function natively using the correct syntax for whatever is passed as if it were being natively called. If you are familiar with PHP internals, you may know that call_user_func_array uses a regex detection pattern under the hood and does not perform all that well. This works identically without the overhead of regex. If you pass more than 14 parameters (you shouldn't ever need to do that), it defers to call_user_func_array normally, and otherwise is no different, except for that it will call anything with fewer than that natively with the correct "->" for objects and "::" for static calls, if either of those apply.

Feel free to use it as is, drop it on an existing class, or convert it to a non-object-oriented function. It solves pretty much all static call bugs like this one, and doesn't collide with anything. If anyone doing core development is reading this, feel free to knock out this as well as a large swath of related bugs with this if you like.

This will work on all versions of PHP from 5.4+, and it's MIT licensed, so it should not collide with the WordPress GPLv2 license, as per the GPL licensing compatibility spec.

I stumbled across this issue because I am still seeing this bug on a clean install of WordPress 4.9 with no plugins aside from Jetpack and Askimet, so it's seemingly still a thing.

Last edited 7 years ago by mopsyd (previous) (diff)

@ComputerGuru
7 years ago

Updated patch and validated against trunk.

#31 follow-up: @ComputerGuru
7 years ago

  • Keywords needs-refresh removed
  • Summary changed from SimplePie error with fetch_feed() to SimplePie non-static WP_Feed_Cache::create error in fetch_feed()

I've uploaded a new patch for this that works against the WP@latest with the currently used version of SimplePie. The workaround was necessitated as SimplePie's own SimplePie_Cache class does not declare create as static, and so we can't just redeclare it as such in our derived WP_Feed_Cache class.

https://core.trac.wordpress.org/attachment/ticket/29204/0001-29204-Fix-errors-about-non-static-WP_Feed_Cache-crea.2.patch

#32 in reply to: ↑ 31 @ksbsb
7 years ago

Thanks A LOT! It works for me.

Replying to ComputerGuru:

I've uploaded a new patch for this that works against the WP@latest with the currently used version of SimplePie. The workaround was necessitated as SimplePie's own SimplePie_Cache class does not declare create as static, and so we can't just redeclare it as such in our derived WP_Feed_Cache class.

https://core.trac.wordpress.org/attachment/ticket/29204/0001-29204-Fix-errors-about-non-static-WP_Feed_Cache-crea.2.patch

#33 in reply to: ↑ 6 @dossy
5 years ago

Replying to l3rady:

I would love to see this fixed as currently we are having to mute this error in Sentry every time we add a WP site.

Five years later ... and I'm glad to know I'm not the only one who tells Sentry to ignore this error until it affects 100,000 more users. *laugh*

Last edited 5 years ago by dossy (previous) (diff)

#34 @stulab
5 years ago

this defect is still alive with the last WordPress version.
I Changed class-wp-feed-cache.php to add static function get_handler

<?php
/**
         * Create a new SimplePie_Cache object
         *
         * @param string $location URL location (scheme is used to determine handler)
         * @param string $filename Unique identifier for cache object
         * @param string $extension 'spi' or 'spc'
         * @return SimplePie_Cache_Base Type of object depends on scheme of `$location`
         */
        public static function get_handler($location, $filename, $extension)
        {
                return new WP_Feed_Cache_Transient($location, $filename, $extension);
        }

        /**
         * Creates a new SimplePie_Cache object.
         *
         * @since 2.8.0
         *
         * @param string $location  URL location (scheme is used to determine handler).
         * @param string $filename  Unique identifier for cache object.
         * @param string $extension 'spi' or 'spc'.
         * @return WP_Feed_Cache_Transient Feed cache handler object that uses transients.
         */
        public function create( $location, $filename, $extension ) {
                return self::get_handler($location, $filename, $extension);
                //return new WP_Feed_Cache_Transient( $location, $filename, $extension );
        }

I had also to change SimplePie/Registry.php to stop the use of create function.

I did it today and it works well

#35 @MadtownLems
5 years ago

Yup, this is still present in 5.4.1; my errors logs are chock full of it.

Is there anything someone who doesn't have a ton of experience contributing to core can help to do see progress? Thanks!

#36 @Ipstenu
5 years ago

SimplePie is being updated in WP 5.5 #36669

So hopefully this will be corrected?

Last edited 4 years ago by SergeyBiryukov (previous) (diff)

#37 @ComputerGuru
5 years ago

There's nothing left to be done, the complete fix is included in #31

#38 @roikles
4 years ago

I'm in the process of testing out WP 5.5 Prior to rolling it out and the first thing we observed within WP admin was this Notice:

Deprecated
Non-static method WP_Feed_Cache::create() should not be called statically
/path/to/wordpress/wp-includes/SimplePie/Registry.php
214

I'm running WordPress version 5.5 using PHP 7.3.9 with all plugins disabled. The error message appears on the dashboard within the 'WordPress Events and News' box. It doesn't appear that the update to SimplePie has fixed the error.

#39 @justlevine
4 years ago

Seemingly this wasn't fixed in 5.5... Let's get this into 5.6?

#40 @hellofromTonya
4 years ago

  • Keywords 4.7-early removed

Related #51559, #51629

@afragen
4 years ago

Combine patches from @dd32 and @ComputerGuru

#41 @afragen
4 years ago

  • Keywords dev-feedback added

29204.3.diff combines 29204.diff and 0001-29204-Fix-errors-about-non-static-WP_Feed_Cache-crea.2.patch

This solves the issue with calling a non-static method and setting the cache.

Possibly fixes #51629

#42 @hellofromTonya
4 years ago

  • Keywords needs-testing added

#43 @joostdevalk
4 years ago

Tested the patch, it works.

#44 @bph
4 years ago

tested it yesterday, too and it works.

#45 @joostdevalk
4 years ago

  • Keywords commit added; needs-testing removed

#46 @SergeyBiryukov
4 years ago

  • Milestone changed from Awaiting Review to 5.6

This ticket was mentioned in Slack in #core by afragen. View the logs.


4 years ago

This ticket was mentioned in Slack in #core by afragen. View the logs.


4 years ago

#49 @OptimizingMatters
4 years ago

tested the patch, can confirm it fixes the severe breakage (critical error) in PHP8 as well.

This ticket was mentioned in Slack in #core by afragen. View the logs.


4 years ago

This ticket was mentioned in Slack in #core by sergey. View the logs.


4 years ago

#52 @hellofromTonya
4 years ago

  • Keywords dev-feedback removed

Ticket has consensus for the implementation. Removing dev-feedback.

#53 @afragen
4 years ago

@SergeyBiryukov with you latest patch I am seeing the error as follows in the dashboard.

( ! ) SCREAM: Error suppression ignored for
( ! ) Deprecated: Non-static method WP_Feed_Cache::create() should not be called statically in /Users/afragen/Local_Beta_Sites/lightning/app/public/wp-includes/SimplePie/Registry.php on line 214
Call Stack
#	Time	Memory	Function	Location
1	0.0003	369960	{main}( )	.../admin-ajax.php:0
2	0.8773	7813640	do_action( )	.../admin-ajax.php:184
3	0.8773	7814016	WP_Hook->do_action( )	.../plugin.php:484
4	0.8773	7814016	WP_Hook->apply_filters( )	.../class-wp-hook.php:311
5	0.8773	7815144	wp_ajax_dashboard_widgets( )	.../class-wp-hook.php:287
6	0.8775	7816784	wp_dashboard_primary( )	.../ajax-actions.php:400
7	0.8779	7817912	wp_dashboard_cached_rss_widget( )	.../dashboard.php:1513
8	0.8795	7846488	wp_dashboard_primary_output( )	.../dashboard.php:1135
9	0.8795	7846864	wp_widget_rss_output( )	.../dashboard.php:1529
10	0.8796	7846864	fetch_feed( )	.../widgets.php:1513
11	0.8812	7870000	SimplePie->init( )	.../feed.php:821
12	0.8817	7872296	SimplePie_Registry->call( )	.../class-simplepie.php:1412
Variables in local scope (#12)
$class =
/Users/afragen/Local_Beta_Sites/lightning/app/public/wp-includes/SimplePie/Registry.php:214:string 'WP_Feed_Cache' (length=13)
$method =
/Users/afragen/Local_Beta_Sites/lightning/app/public/wp-includes/SimplePie/Registry.php:214:string 'get_handler' (length=11)
$parameters =
/Users/afragen/Local_Beta_Sites/lightning/app/public/wp-includes/SimplePie/Registry.php:214:
array (size=3)
  0 => string './cache' (length=7)
  1 => string '9bbd59226dc36b9b26cd43f15694c5c3' (length=32)
  2 => string 'spc' (length=3)
$result =
Undefined
$type =
/Users/afragen/Local_Beta_Sites/lightning/app/public/wp-includes/SimplePie/Registry.php:214:string 'Cache' (length=5)

This might be from cached transient.

Last edited 4 years ago by afragen (previous) (diff)

#54 follow-up: @afragen
4 years ago

I have not been able to reproduce the above error after deleting the cached transient and testing the patch.

Looks good.

#55 @SergeyBiryukov
4 years ago

For reference, here is a minimal snippet to reproduce the issue in question:

class My_Test_Class {

	public function create() {
	}

}

call_user_func( array( 'My_Test_Class', 'create' ) );

As noted in comment:19 and seen in test runs, this causes different results in different versions of PHP:

  • E_STRICT notice in PHP 5:
    Strict Standards: call_user_func() expects parameter 1 to be a valid callback, non-static method My_Test_Class::create() should not be called statically
  • E_DEPRECATED notice in PHP 7:
    Deprecated: Non-static method My_Test_Class::create() should not be called statically
  • A fatal error in PHP 8:
    Uncaught TypeError: call_user_func(): Argument #1 ($function) must be a valid callback, non-static method My_Test_Class::create() cannot be called statically

In case of SimplePie, this is a bit tricky to reproduce, because the affected call_user_func_array() call is silenced with the @ operator, but it becomes more obvious with the fatal error in PHP 8.

This appears to be a long-standing issue in SimplePie back from 1.2.x versions.

Some history on the related changes:

  • [21644] / #21183 updated SimplePie to 1.3, including marking both SimplePie_Cache::create() and WP_Feed_Cache::create() as static.
  • [21652] / #21183 briefly used a newer approach to register the cache handler in the same way as suggested in 29204.diff. Per SimplePie documentation, registering a cache handler is indeed the recommended approach for SimplePie 1.3 or later, overriding the SimplePie_Cache class is no longer needed.
  • SimplePie 1.3.1 included a commit that reverted the addition of static keyword for SimplePie_Cache::create() and introduced the SimplePie_Cache::get_handler() method instead.
  • [22366] / #22321 updated SimplePie to 1.3.1 in core.
  • [22599] / #22321 removed the compatibility code added in [21652], see comment:11:ticket:22321 for the reasoning. The concern was that plugins could include earlier versions, so the legacy approach seemed good enough at the time, but did not account for the silenced notices that became more severe in later PHP versions and now result in a fatal error on PHP 8.

Looking at 29204.3.diff, it combines both approaches suggested here earlier, which seems a bit redundant:

  • Changing WP_Feed_Cache to no longer depend on SimplePie_Cache, in order to add the static keyword. Since that is a legacy method that should have only been used for SimplePie 1.2 or earlier, I don't think that is the correct path to take here. The whole class-wp-feed-cache.php file should be deprecated instead.
  • Registering and using a cache handler, as suggested in 29204.diff. I believe that is the way to go here.

In 29204.4.diff:

  • Use the recommended approach of registering a cache handler from SimplePie documentation.
  • Mark the wp-includes/class-wp-feed-cache.php file as deprecated.
  • Add a back-compat check to avoid a fatal error in case there are still plugins out there including SimplePie 1.2.x.
  • Tested on PHP 8.0.0RC4, 7.4.12, and 5.6.40.

#56 in reply to: ↑ 54 @SergeyBiryukov
4 years ago

Replying to afragen:

I have not been able to reproduce the above error after deleting the cached transient and testing the patch.

Thanks for testing! Yeah, the legacy ::create() method should not be called at all with the patch. A cached transient did not affect that in my testing, though I only tested by calling fetch_feed() directly and displaying the results.

#57 @SergeyBiryukov
4 years ago

#51629 was marked as a duplicate.

#58 @SergeyBiryukov
4 years ago

  • Resolution set to fixed
  • Status changed from reviewing to closed

In 49565:

Feeds: Register transient feed cache handler using the recommended method for SimplePie 1.3 or later.

This fixes a "Non-static method cannot be called statically" fatal error when calling fetch_feed() on PHP 8.

Follow-up to [21644], [21652], [22366], [22599].

Props dd32, afragen, Senning, markoheijnen, ComputerGuru, useStrict, Ipstenu, nacin, l3rady, HoaSi, NathanAtmoz, fabifott, jfoulquier, thefarlilacfield, subscriptiongroup, rogerlos, Mte90, mopsyd, dossy, stulab, MadtownLems, roikles, justlevine, joostdevalk, OptimizingMatters, hellofromTonya, bph, ayeshrajans, SergeyBiryukov.
Fixes #29204.

Note: See TracTickets for help on using tickets.