Skip to:
Content

BuddyPress.org

Opened 8 years ago

Closed 8 years ago

Last modified 8 years ago

#7227 closed defect (bug) (fixed)

Fatal error - Call to undefined function wp_generate_password() in bp-core\bp-core-options.php on line 77

Reported by: r-a-y's profile r-a-y Owned by: djpaul's profile djpaul
Milestone: 2.7 Priority: high
Severity: major Version:
Component: Core Keywords: has-patch
Cc:

Description

If a plugin is activated and loads before the 'plugins_loaded' hook and calls on one of these functions:

  • update_option()
  • update_site_option()
  • add_option()
  • add_site_option()

You will get the Call to undefined function wp_generate_password() in bp-core\bp-core-options.php on line 77 fatal error.

The problem is caused by the bp_core_clear_root_options_cache() function, which is hooked to the above function hooks, and the introduction of the bp-emails-unsubscribe-salt root option in r10949, which uses wp_generate_password() in bp_get_default_options().

wp_generate_password() is only available via wp-includes/pluggable.php. wp-includes/pluggable.php is loaded after plugins are included:
https://core.trac.wordpress.org/browser/tags/4.6/src/wp-settings.php?marks=230,238,272,278#L228

So if a plugin uses either update_option(), update_site_option(), add_option() or add_site_option() before the 'plugins_loaded' hook, you will get the fatal error described above.

I've attached a patch that includes pluggable.php if it isn't available, which fixes the issue.

I think we also have to audit the bp_core_clear_root_options_cache() function. On a multisite network, do we have to check this function on all sub-sites? Wouldn't it make sense to only use this function on the root blog?

Attachments (2)

7227.01.patch (445 bytes) - added by r-a-y 8 years ago.
7227.diff (3.7 KB) - added by DJPaul 8 years ago.

Download all attachments as: .zip

Change History (29)

@r-a-y
8 years ago

This ticket was mentioned in Slack in #buddypress by r-a-y. View the logs.


8 years ago

#2 @r-a-y
8 years ago

To further clarify, this fatal error only pops up on upgrades to BP 2.7 and when a plugin is doing what I mentioned in the OP.

To duplicate this error, you can add and activate the following test plugin:

<?php
/*
 Plugin Name: BP 7227 - Fatal error
 Plugin URI: https://buddypress.trac.wordpress.org/ticket/7227
 Description: Fatal error caused by wp_generate_password()
 */

// Emulate upgrade to BP 2.7 by first removing the email salt.
delete_option( 'bp-emails-unsubscribe-salt' );

// Update any option in the database with BuddyPress 2.7-alpha activated.
update_option( 'raytest', time() );

#3 @DJPaul
8 years ago

I have revisited this area of code since working on another patch. bp_get_default_options() is getting called on every page load, via bp_core_set_avatar_constants(), which causes options to be added if they're missing in the database. See near the "Missing some options, so do some one-time fixing." bit. I'm tempted to remove those fixer lines, because I'm not sure why they are there. Anyone else think it's a good idea?

That aside, for upgrades, bp_update_to_2_7() is instantly updating the option with a new key. New installs would have gotten it set via... I'm not sure how, probably working on the assumption that bp_get_default_options would run once via bp_add_options().

To avoid having to include pluggable.php, because i'm worried about causing load-order issues with other plugins that override pluggable function, how about:

1) We update bp_core_get_root_options() and prevent it adding "missing options".
2) And we update bp_get_default_options() and add a note saying that this function should not rely on any WordPress functions.
3) As a consequence, we set the default value of bp-emails-unsubscribe-salt to an empty string in bp_get_default_options.
4) We continue to set bp-emails-unsubscribe-salt in bp_update_to_2_7, but we add setting it in bp_version_updater in the bp_is_install() bit, thus setting it for new installs.

This should stop a "get" function setting database values, prevent the fatal error that this ticket describes, and make it clearer where the default options are set for on new install/update.

(I don't think we should set bp-emails-unsubscribe-salt in bp_core_install_emails() because that can be called from one of the BP Tools, and updating this nonce will break all previous unsubscribe nonces.)

Last edited 8 years ago by DJPaul (previous) (diff)

@DJPaul
8 years ago

#4 @DJPaul
8 years ago

So I tried to patch this the way I described above (in 7227.diff - sorry for suffixed file name, I am trying out grunt upload_path). However, the red in the patch breaks a number of unit tests: https://gist.github.com/paulgibbs/bd4882d283f87c565febb341da149cbd -- they seem to be focused around post tracking/post filters, but I can't understand why the removal of the code breaks these.

I spent an hour chasing a rabbit down a hole, so I'm not sure exactly what the cause is yet. Unless it doesn't like false for the default value of options, which causes something else to misbehave, and so on. To reproduce, run phpunit with this patch on a clean DB (i.e. new WP install, tested on non-multisite).

This ticket was mentioned in Slack in #buddypress by djpaul. View the logs.


8 years ago

#6 @DJPaul
8 years ago

Figured this out. Patch incoming.

This ticket was mentioned in Slack in #buddypress by djpaul. View the logs.


8 years ago

#8 @djpaul
8 years ago

  • Owner set to djpaul
  • Resolution set to fixed
  • Status changed from new to closed

In 11093:

BuddyPress, Emails: set value of bp-emails-unsubscribe-salt option for new installs.

The initial value was set in bp_get_default_options() and worked because that function adds missing options to the database when it's ran.
For version updates, the new option was already being explictly added elsewhere.

However if a plugin is active and loads before the plugins_loaded hook, and calls add_option() or update_option() (or multisite equivalents), a fatal error is caused by the bp_core_clear_root_options_cache()` function.
This is because wp_generate_password() in used in bp_get_default_options() to set the bp-emails-unsubscribe-salt option, which is only available via wp-includes/pluggable.php. That file is only loaded by WordPress after plugins are loaded.

This change sets the default value in bp_get_default_options(), and then explicitly updates the value to the unsubscribe halts in the existing email installation function.

Fixes #7227
See #7254

Props r-a-y, DJPaul

#9 @djpaul
8 years ago

In 11094:

Core: stop bp_get_default_options() adding missing options to the database.

bp_get_default_options() is used to get default option names and values throughout BuddyPress. If an option is not set in the database when the function is ran, it will add it.
The function is called in lots of places, and it even gets called before the version update handler routine does, from bp_core_set_avatar_constants().
This is not obvious, and causes unpredictable behaviour about when a new option should exist (or not).

This change removes the missing option insertion from bp_get_default_options().
New installs will have all options added by bp_activation(). Version updates will take responsibility to add new options within the existing upgrade routines.

See #7254 and #7227

#10 @jana307
8 years ago

Hello!

I currently have this issue on my site and not sure how to resolve it. My homepage is showing this message (which wasn't there about a week ago when I last logged in).

Fatal error - Call to undefined function wp_generate_password() in bp-core\bp-core-options.php on line 77

What can I do to get back access to my site and resolve this?

Thanks!
Jana

#11 @DJPaul
8 years ago

@jana307 What version of BuddyPress are you running?

#12 @jana307
8 years ago

I can't tell without going in to check :-( Does it help to know that I installed it about 7-8 days ago?

#13 @DJPaul
8 years ago

Where did you install it from - how?

#14 @jana307
8 years ago

Through the Wordpress plugin dashboard (Add new --> looked up BuddyPress).

#15 @DJPaul
8 years ago

Ok. To fix your site, you'll need to FTP in -- go into wp-content/plugins, find the "BuddyPress" folder, rename it to something else. Then visit your-site.com/wp-admin/plugins.php, and it should deactivate the BuddyPress plugin.

#16 @jana307
8 years ago

Great, thanks! I'm waiting for FTP credentials (it's for a client). After I disable it, what should I do to fix it? We'd like to keep using it!

This ticket was mentioned in Slack in #buddypress by djpaul. View the logs.


8 years ago

#18 @DJPaul
8 years ago

The line referenced in your error does not exist in BuddyPress version 2.6.2, which is the current release. It is part of new code for our next version, BuddyPress 2.7, which is undergoing testing.

Please would you check and confirm if you or your client decided to manually update BuddyPress to 2.7 Beta 1? Or fetched the SVN trunk version, or a Git master branch from somewhere? You said you installed the plugin via wp-admin, so I don't know how you would have gotten 2.7 Beta 1 without manual intervention. There's a tiny possibility WordPress.org had a temporary fault and did something wrong, but that's not very likely at this stage.

#19 @jana307
8 years ago

I'll see what I can find out when I'm back in. My client didn't touch it for sure. If you know how I can tell whether I've updated to 2.7 through the regular "update plugin" functionality in WP dashboard (that somehow showed up but shouldn't), please let me know and I'm happy to check that log. No idea what SVN trunk or Git master means so no, didn't do that :-)

#20 @DJPaul
8 years ago

Ok, so even after you rename the plugin folder (to get WP to stop trying to load it), you'll still see it listed in the plugins list, something like this: https://cloudup.com/cVGROn0wG5B

See where it says "Version 2.7 Beta 1"? That's the version number of the plugin installed.

Assuming it is not 2.6.2, I'd suggest deleting the plugin, re-installing it (via wp-admin like normal), and before you activate, double-check it says 2.6.2.

#21 @jana307
8 years ago

Got it - will circle back when I have the info!

#22 @jana307
8 years ago

Got it! It's 2.7-alpha!

#24 follow-up: @r-a-y
8 years ago

@jana307 - Are you sure you were the one that updated BuddyPress through the dashboard? Does anyone else manage your site that could have manually uploaded the 2.7-alpha version?

The error message you listed is based on an older, development version of BuddyPress.

Current stable version on wordpress.org is 2.6.2. We also have 2.7-beta-1 out as well, but you would need to manually upload it to your server and not through the dashboard.

Since you are already using 2.7-alpha, I would recommend testing 2.7-beta-1. 2.7-beta-1 should (hopefully) also fix your fatal error:
https://buddypress.org/2016/09/buddypress-2-7-0-beta-1/


Can you check one other thing? Can you check in your wp-content/plugins/buddypress folder if one of the following directories exists? .svn or .git?

Last edited 8 years ago by r-a-y (previous) (diff)

#25 in reply to: ↑ 24 @jana307
8 years ago

@r-a-y Nobody accessed the site and I introduced this plugin to the client so it's all me. I don't remember if I updated it or was it just the initial installation that was already that version (though if it was, why would it work when I was setting it up and then stop at some point?). I have a faint memory of clicking "update now" on this plugin from the plugin list but can't be sure... I just checked on another site I installed it and it's version 2.6.2 and there's no "update now" link there.

#26 @jana307
8 years ago

No .svn or .git folders: http://pasteboard.co/92M1o0A0T.png
And it looks like I installed in on Friday Sep 23.

This ticket was mentioned in Slack in #buddypress by r-a-y. View the logs.


8 years ago

Note: See TracTickets for help on using tickets.