Re: bp_setup_nav not firing
Okay, I’ve just gone through BP core and commented out all references to the plugins_loaded event accept for in bp-loader.php. I then refactored these references to hook into bp-init instead. All hooks worked fine accept bp-setup-nav. I had to set it to no priority or a priority lower than ten to make my navigation items show up in my plugin.
So, I outputted the various do_action arrays and discovered the issue. It is as I thought above–somewhat.
Not only does WordPress search for action calls top-down and alphabetically, it then reorders all action calls for a given hook by priority and if no priority is given, by the order in which it first came across a given action reference. Yes, I know, this is probably confusing most of you. Without seeing the output it may be too complex to visualize.
Here’s why my navigation menu was not showing up:
– All third-party plugins are now supposed to hook into the bp-init event
– The function in my plugin’s loader file that does that is called ‘BPAz_init’. It hooks into bp-init as follows:
add_action( 'bp_init', 'BPAz_init' );
– As you can see, I do not set a load priority on that action
– With the bp_setup_nav event (see line 2025 in bp-core.php) now tied to the bp-init event, instead of plugins_loaded, in my test core hack, and without setting any priority
add_action( 'bp_init', 'bp_setup_nav' );
it gets fired after my BPAz_init function and my plugin’s navigation menu appears
– But, if I set a priority below 10 for the bp_setup_nav event, my navigation fails to load. If I set a priority above 10, it loads. So,
add_action( 'bp_init', 'bp_setup_nav', 9 );
does not work, but,
add_action( 'bp_init', 'bp_setup_nav', 11);
works. My plugin’s navigation appears and functions.
So, the question is why?
Here’s the answer. It has to do with the fact that the function in my loader file that calls the bp-init event is found in a file that comes alphabetically before the file in which the function bp_setup_nav exists.
So, my function BPAz_init lives in a file found in /bp-authz/bp-authz-loader.php but function bp_setup_nav lives in /buddypress/bp-core.php. When the do_action function is processing the array, it sorts them first by priority and second by the order in which they were first loaded. Since my initialization function lives in a subdirectory that is searched before the buddypress subdirectory, my function that is hooked into the bp-init event is discovered before the bp_setup_nav action. This means that if no priorities are set for either function, things just happen to work fine by simple virtue of my plugin directory having a lower alphabetical order and thus higher search priority.
But if I set the priority for the bp_setup_nav action to be higher than ten (as in 9 or lower), then it is fired before my plugin is ever initialized and therefore my navigation menus cannot be rendered. If I set the priority for the bp_setup_nav action lower than ten (as in a number equal to or greater than 11), then my plugin is initialized before the bp_setup_nav event and my navigation menus work.
If I had not serendipitously named my file to something that has a higher alphabetical order than “buddypress”, I may never have discovered this issue. But, the moral of the story is this: the bp_setup_nav event must occur after all BP-dependent plugin’s have been initialized, otherwise their navigation menus will not appear. So, with the bp_setup_nav event tied to plugins_loaded, it fires before all BP-dependent plugin’s have been initialized. But, by setting a low-enough priority, it is possible to push that particular action of plugins_loaded to after all the BP-dependent plugin’s have been initialized. This is, of course, not the best way to do this.
As there may be other BP actions that are loaded too soon, I will need to spend a little time figuring out what this means for all the other action hooks in BuddyPress and BP-dependent plugins. The order in which an action fires can obviously be crucial. Since the firing order is based first on priority set, then on the alphabetical name of the functions that call a given hook, this can result in unexpected behavior.
Confused? Me too!