#25247 closed defect (bug) (fixed)
WP_Dependencies unsets a to do item when it isn't loaded
Reported by: |
|
Owned by: |
|
---|---|---|---|
Milestone: | 4.5 | Priority: | normal |
Severity: | normal | Version: | 3.6 |
Component: | Script Loader | Keywords: | has-patch has-unit-tests |
Focuses: | Cc: |
Description
Currently it unsets $this->to_do no matter if do_item() return true or false. For example If you move jquery to the footer it will not load jquery at all. since it thinks jquery-core is loaded.
add_action( 'wp_default_scripts', 'move_jquery_to_footer_and_not_load_migrate' ); public function move_jquery_to_footer_and_not_load_migrate( &$scripts ) { if( ! is_admin() ) { $scripts->registered['jquery']->deps = array( 'jquery-core' ); $scripts->add_data( 'jquery', 'group', 1 ); $scripts->add_data( 'jquery-core', 'group', 1 ); } }
Attachments (17)
Change History (51)
#3
follow-up:
↓ 25
@
11 years ago
- Cc azaozz added
- Keywords needs-patch added
- Milestone changed from Awaiting Review to Future Release
- Version set to 3.6
This script has worked until 3.6:
/** * Prints jQuery in footer on front-end. */ function ds_print_jquery_in_footer( &$scripts) { if ( ! is_admin() ) $scripts->add_data( 'jquery', 'group', 1 ); } add_action( 'wp_default_scripts', 'ds_print_jquery_in_footer' );
With 3.6 I would set the group arg for the dependencies to 1 too, but that doesn't work.
#5
@
11 years ago
- Keywords has-patch added; needs-patch removed
I added a patch for this. I found that the function was adding jquery to the 'done' array as it doesn't have an src set (src is set on jquery-core).
What's currently happening is when it is doing the footer items, jquery is already in the done array and it makes no attempt to load it.
I've added a patch that checks the current group and set group (if isset) on the item when adding to the done array in the !(has-src) conditional.
For this to work, just set the jQuery and its dependencies' group to 1 with the wp_default_scripts action.
#7
@
10 years ago
Tested the patch #25247_bugfix.diff on WordPress 4.0 on a site with a variety of javascript files with dependencies. jQuery is loaded in the footer as expected, in first place so all depending scripts are loaded after it, using Marko's function.
Would be great to get this merged in, as scripts should really load in the footer
#8
@
10 years ago
Hey fellas,
I submitted a revised patch that makes the conditional more readable by expressing some of the conditions as variables and ensured that spacing etc follows the WordPress PHP coding standards.
#9
in reply to:
↑ 1
@
10 years ago
@nacin would you like this to be a test for WP_Scripts
or WP_Dependencies
?
Edit: I need to use a method from WP_Scripts
to test this properly, but all the code changes are in the parent class WP_Dependencies
. Should I put the test in Tests_Dependencies_Scripts
or Tests_Dependencies
?
#10
@
10 years ago
- Keywords needs-unit-tests removed
Ok.
Since it relies on the WP_Scripts
version of the do_item
method, I put the unit test in tests/dependencies/scripts.php
.
I also verified that it fails without my patch and passes with my patch.
Please Note: If you are testing, I have put the unit test and the core fix in 2 separate patches so you'll need both:
[Core Patch](https://core.trac.wordpress.org/attachment/ticket/25247/%2325247_bugfix_v2.diff)
[Unit Test](https://core.trac.wordpress.org/attachment/ticket/25247/25247-unit-test.diff)
#11
@
10 years ago
I think the no src issue is a bit of a red herring. The real problem here - as stated by the OP markoheijnen - is that the do_items() loop is removing an item from the to_do list whether or not it succeeded. An issue reported by helgatheviking on WP stackexchange (Loading a script with a dependency, is unloading another script's dependency is another symptom of the problem, which can be seen simply with this setup:
$scripts = new WP_Scripts; $scripts->add( 'jquery-ui-datepicker', 'one', array(), 'v1', 1 ); $scripts->add( 'wc-admin-meta-boxes', 'two', array( 'jquery-ui-datepicker' ) ); $scripts->add( 'My_Plugin_Metabox', 'three', array( 'wc-admin-meta-boxes' ), 'v1', 1 ); $scripts->enqueue( array( 'My_Plugin_Metabox' ) ); $scripts->do_items( false, 0 ); $scripts->do_items( false, 1 );
Note the mismatch in groups between 'wc-admin-meta-boxes' and 'jquery-ui-datepicker', If you run this, 'jquery-ui-datepicker' won't be outputted, it's just appended to the $in_footer array in WP_Scripts and left there, and since the array is no longer used in do_footer_items(), it gets lost.
Basically it seems that when the code was changed to do two passes of do_items() instead of one, the loop wasn't updated. The fix is simple, only remove the item from the to_do list when it's successfully added (or when the src is null).
The helgatheviking scenario also shows up another issue, in that although with the loop fix 'jquery-ui-datepicker' will get outputted, it will output in the footer, after the dependent 'wc-admin-meta-boxes' which gets outputted in the head. To fix this it would seem best to force any dependencies to the lowest common group, which can I think be achieved by setting the class $this->group when recursing in set_group().
I'll attach a patch and unit tests with these changes.
#12
@
10 years ago
Also the following is an optional patch to WP_Scripts, removing references to the vestigal $in_footer array, and also replacing the use of item $args === 1 with add_data('group', 1) (by overriding the add() function) - having the group state in two separate variables is not the best idea and no doubt legacy again...
#14
@
10 years ago
Would like to see this bug get more attention, it's 18 months old and in a fundamental part of WP which shouldn't have bugs (and where some non-bug changes seem to be getting more consideration).
#16
@
10 years ago
Just got hit by this as well, using a clean installation of WP 4.3. Hopefully the above patches get merged soon.
#17
@
9 years ago
Refresh for 4.5 Bug Scrub. 25247_dependencies.diff and 25247_tests3.diff still good.
This ticket was mentioned in Slack in #core by chriscct7. View the logs.
9 years ago
#21
@
9 years ago
Per https://wordpress.slack.com/archives/core/p1454692115001728, set since to 4.5 on overridden add() in class.wp-scripts.php.
#23
@
9 years ago
@gitlost Can you please combine the patches into one patch? It's currently unclear which patches need to be applied.
#25
in reply to:
↑ 3
@
9 years ago
Replying to ocean90:
This script has worked until 3.6:
/** * Prints jQuery in footer on front-end. */ function ds_print_jquery_in_footer( &$scripts) { if ( ! is_admin() ) $scripts->add_data( 'jquery', 'group', 1 ); } add_action( 'wp_default_scripts', 'ds_print_jquery_in_footer' );With 3.6 I would set the group arg for the dependencies to 1 too, but that doesn't work.
After [36550] this is working now:
<?php /** * Prints jQuery in footer on front-end. */ function ds_print_jquery_in_footer( &$scripts) { if ( ! is_admin() ) { $scripts->add_data( 'jquery-core', 'group', 1 ); $scripts->add_data( 'jquery', 'group', 1 ); $scripts->add_data( 'jquery-migrate', 'group', 1 ); } } add_action( 'wp_default_scripts', 'ds_print_jquery_in_footer' );
#26
@
9 years ago
- Keywords dev-feedback removed
@gitlost Thanks! So let's ignore the scripts part for now.
I've removed the change to unset( $this->to_do[$key] );
and the tests are still passing. Is this change still necessary? If yes, we need a test which fails before the change.
#27
follow-up:
↓ 29
@
9 years ago
No, I don't think the change is necessary (although it seems more logical to me) and I don't have a failing test so I suppose it's turned into a bit of a hijack now given [36550] so this ticket should probably now be closed (and the proposed removal of the legacy scripts stuff put into a new ticket)?
#29
in reply to:
↑ 27
@
9 years ago
- Keywords needs-testing removed
- Milestone changed from Future Release to 4.5
Replying to gitlost:
No, I don't think the change is necessary (although it seems more logical to me) and I don't have a failing test so I suppose it's turned into a bit of a hijack now given [36550] so this ticket should probably now be closed (and the proposed removal of the legacy scripts stuff put into a new ticket)?
Yes, please create a ticket for the scripts change and I'll add your test test_group_mismatch_in_deps()
to #35873.
I'm going to close this ticket as fixed since the original issue is fixed, see [36596].
#31
@
9 years ago
- Resolution fixed deleted
- Status changed from closed to reopened
I have recently encountered this myself. If you force a item to the footer, but it has dependencies, the dependencies may not go to the footer at all due to being removed from the to_do array. An example is forcing the "jquery" script alias to the footer.
<?php add_action('wp_print_scripts', function () { if (!is_admin()) { $jquery = wp_scripts()->registered['jquery']; wp_dequeue_script('jquery'); wp_deregister_script('jquery'); wp_register_script('jquery', $jquery->src, $jquery->deps, $jquery->ver, true); } }, 0);
This is relying on jquery to be a dependency to other items. So it is more of a 2nd level dependency issue.
A very simple 2-3 line patch is attached
Could you submit a unit test patch demonstrating the issue?