Opened 15 years ago
Closed 14 years ago
#5265 closed defect (bug) (invalid)
current_user_can() can run before wp_get_current_user() is defined
Reported by: |
|
Owned by: | |
---|---|---|---|
Milestone: | Priority: | normal | |
Severity: | normal | Version: | 2.3.1 |
Component: | Administration | Keywords: | |
Focuses: | Cc: |
Description
Okay, so I'm writing a plugin and here's the code I have so far:
http://wordpress.pastebin.com/f3ea57b78
When activating the plugin from the plugins page, I get the following error:
Fatal error: Call to undefined function wp_get_current_user() in [...]\wp-includes\capabilities.php on line 446
No, it's not in a blue box or anything -- it's just that error message. I have to go and rename or delete the plugin file to get my admin area back.
So two issues here:
A) What's causing this PHP error?
B) Why isn't it being caught by the box and dying gracefully? (I assume it's because the error isn't in the plugin's file.)
Change History (11)
#2
@
15 years ago
- Summary changed from Possible to get "call to undefined function" when activating a plugin to current_user_can() can run before wp_get_current_user() is defined
#3
@
15 years ago
The problem here is you plugin is running code when included.
That is a bad plan.
You should run your setup code on the plugins_loaded or init hook like so:
add_action('plugins_loaded', create_function('','global $WPcomAdminBar; $WPcomAdminBar = new WPcomAdminBar()'));
This ensures that all the WordPress functions are available before your code runs.
#4
@
15 years ago
Yeah, I'm being bad in my coding skills (thanks for that slick class start code BTW), but still, shouldn't pluggable.php
be loaded before capabilities.php
?
#5
follow-up:
↓ 6
@
14 years ago
- Keywords needs-patch removed
- Milestone 2.3.2 deleted
- Resolution set to invalid
- Status changed from new to closed
- Version 2.3 deleted
I cant see any reason for pluggable.php to be loaded before capabilities.php,
If you follow coding guidelines and use the hook as westi mentioned, there are no issues. current_user_can() shouldnt be needed until all plugins and pluggable.php is loaded anyway.
Closing as invalid.
#6
in reply to:
↑ 5
;
follow-up:
↓ 7
@
14 years ago
- Severity changed from blocker to normal
- Version set to 2.3.1
Replying to DD32:
I cant see any reason for pluggable.php to be loaded before capabilities.php,
Because capabilities.php
is calling a function defined in pluggable.php
?
#7
in reply to:
↑ 6
;
follow-up:
↓ 8
@
14 years ago
Replying to Viper007Bond:
Replying to DD32:
I cant see any reason for pluggable.php to be loaded before capabilities.php,
Because
capabilities.php
is calling a function defined inpluggable.php
?
I meant in normal operation, current_user_can()
wouldnt be called until after plugins and pluggable.php
had been loaded.
#8
in reply to:
↑ 7
;
follow-up:
↓ 9
@
14 years ago
- Milestone set to 2.4
- Resolution invalid deleted
- Status changed from closed to reopened
Replying to DD32:
I meant in normal operation,
current_user_can()
wouldnt be called until after plugins andpluggable.php
had been loaded.
Correct, and I fixed my plugin to do that, but you shouldn't be able to call a defined function properly and get WordPress to make a fatal PHP error as a result. It's bad coding practice in my book. Having the function not work as intended (like returning a null result) is one thing, but literally breaking is another.
current_user_can()
should either be defined later (and therefore be an undefined function at the time of plugin loading) or better yet, should not use functions not loaded yet.
So three possible solutions:
- Load
pluggable.php
before any user script is able to run so thatcurrent_user_can()
won't throw a PHP error
- Put a
function_exists()
check inside ofcurrent_user_can()
so that it can't run until everything it needs to operate is loaded
- Move
capabilities.php
to after plugins are loaded (seems like a bad idea)
I hate to get in an open/close war, but WordPress shouldn't throw PHP errors if a plugin calls a defined function correctly, no matter what. It needs abort gracefully.
#9
in reply to:
↑ 8
@
14 years ago
Replying to Viper007Bond:
- Load
pluggable.php
before any user script is able to run so thatcurrent_user_can()
won't throw a PHP error
Well that option is useless, It needs to be loaded after plugins to allow plugins to override them.
- Put a
function_exists()
check inside ofcurrent_user_can()
so that it can't run until everything it needs to operate is loaded
That could work, If function doesnt exist, then user cannot perform operation, Which would backfire on anything requesting the action anyway, the function doesnt know yet if a user can or cant perform the action, returning null instead might be an option, But will still be interprated as a negitive response to most code.
- Move
capabilities.php
to after plugins are loaded (seems like a bad idea)
That could work, But what about functions in the other set of files loaded before the plugins? What if they require a function in capabilities.php
?, or a function in pluggable.php
, Should we move those after plugins are loaded too?
At least some of the files need to be loaded before plugins (database/get_option/sanitize_option/etc), All which require another function, which requires another.. Eitherway, You'll find another function which will need a function which is undefined at that stage.
Thats why plugin_loaded/init hooks are provided, To allow for code to be run once WP has loaded all its files, and is ready to work as intended, Until that time comes, Any code in any file(be it WP's or a Plugins) cant expect all functions to behave as intended.
I hate to get in an open/close war
And for that reason, I'll not touch the status of it
#10
follow-up:
↓ 11
@
14 years ago
For what it is worth, I agree with DD32. It is unacceptable to assume that functions will exist without hooking into init hook first. So naturally, anything plugin that doesn't follow this principle has a bug in the plugin and not in WordPress. It is a limitation of the language and therefore seems illogical to assume that functions will be available before PHP knows about it.
Just because a function makes reference to a function that may not exist at that time, doesn't mean it will break anything until the function is called that contains the function in question.
As for fixing the pluggables, there is a pattern that would be useful. I forget what the name is. Hmm, related to Dependency Interjection, but I don't think that is the correct name for the pattern. No matter.
WTF? Returning null in a constructor, that is plain bad practice right there. You should know better than that!
#11
in reply to:
↑ 10
@
14 years ago
- Milestone 2.4 deleted
- Resolution set to invalid
- Status changed from reopened to closed
Replying to darkdragon:
For what it is worth, I agree with DD32. It is unacceptable to assume that functions will exist without hooking into init hook first. So naturally, anything plugin that doesn't follow this principle has a bug in the plugin and not in WordPress. It is a limitation of the language and therefore seems illogical to assume that functions will be available before PHP knows about it.
I don't think there's any disagreement there.
My point though is that I'm not calling a function that doesn't exist, I'm calling one that does and that's causing all of WordPress to break and that there should be some error handling there. One would think that any function defined at the time custom code is run would be expected to work or that otherwise it'd be undefined, but maybe that's just me...
But anyway, I'll re-mark as invalid since the proper practice is to not run anything at plugin load.
WTF? Returning null in a constructor, that is plain bad practice right there. You should know better than that!
Heh, I wasn't actually putting that forward that exact solution, just that perhaps it'd be best for the function to fail gracefully. ;)
The issue is due to this line:
current_user_can()
is defined at the time this plugin runs, but it appearspluggable.php
hasn't been loaded yet.