Skip to content
Open
31 changes: 29 additions & 2 deletions src/wp-includes/class-wp-dependencies.php
Original file line number Diff line number Diff line change
Expand Up @@ -199,10 +199,19 @@ public function all_deps( $handles, $recursion = false, $group = false ) {
continue;
}

$keep_going = true;
$keep_going = true;
$missing_dependencies = array();
if ( isset( $this->registered[ $handle ] ) && count( $this->registered[ $handle ]->deps ) > 0 ) {
$missing_dependencies = array_diff( $this->registered[ $handle ]->deps, array_keys( $this->registered ) );
}
if ( ! isset( $this->registered[ $handle ] ) ) {
$keep_going = false; // Item doesn't exist.
} elseif ( $this->registered[ $handle ]->deps && array_diff( $this->registered[ $handle ]->deps, array_keys( $this->registered ) ) ) {
} elseif ( count( $missing_dependencies ) > 0 ) {
_doing_it_wrong(
__METHOD__,
$this->get_dependency_warning_message( $handle, $missing_dependencies ),
'7.0.0'
);
$keep_going = false; // Item requires dependencies that don't exist.
} elseif ( $this->registered[ $handle ]->deps && ! $this->all_deps( $this->registered[ $handle ]->deps, true, $new_group ) ) {
$keep_going = false; // Item requires dependencies that don't exist.
Expand Down Expand Up @@ -535,4 +544,22 @@ public function get_etag( $load ) {
*/
return 'W/"' . md5( $etag ) . '"';
}

/**
* Gets a dependency warning message for a handle.
*
* @since 7.0.0
*
* @param string $handle Handle with missing dependencies.
* @param string[] $missing_dependency_handles Missing dependency handles.
* @return string Formatted, localized warning message.
*/
protected function get_dependency_warning_message( $handle, $missing_dependency_handles ) {
return sprintf(
/* translators: 1: Handle, 2: Comma-separated list of missing dependency handles. */
__( 'The handle %1$s was enqueued with dependencies that are not registered: %2$s.' ),
$handle,
implode( ', ', $missing_dependency_handles )
);
}
}
14 changes: 13 additions & 1 deletion src/wp-includes/class-wp-script-modules.php
Original file line number Diff line number Diff line change
Expand Up @@ -722,7 +722,19 @@ private function sort_item_dependencies( string $id, array $import_types, array
}

// If the item requires dependencies that do not exist, fail.
if ( count( array_diff( $dependency_ids, array_keys( $this->registered ) ) ) > 0 ) {
$missing_dependencies = array_diff( $dependency_ids, array_keys( $this->registered ) );
if ( count( $missing_dependencies ) > 0 ) {
_doing_it_wrong(
__METHOD__,
sprintf(
/* translators: 1: Script module ID, 2: Comma-separated list of missing dependency IDs. */
__( 'The script module %1$s was enqueued with dependencies that are not registered: %2$s.' ),
$id,
implode( ', ', $missing_dependencies )
),
'7.0.0'
);

return false;
}

Expand Down
18 changes: 18 additions & 0 deletions src/wp-includes/class-wp-scripts.php
Original file line number Diff line number Diff line change
Expand Up @@ -1164,4 +1164,22 @@ public function reset() {
$this->ext_version = '';
$this->ext_handles = '';
}

/**
* Gets a script-specific dependency warning message.
*
* @since 7.0.0
*
* @param string $handle Script handle with missing dependencies.
* @param string[] $missing_dependency_handles Missing dependency handles.
* @return string Formatted, localized warning message.
*/
protected function get_dependency_warning_message( $handle, $missing_dependency_handles ) {
return sprintf(
/* translators: 1: Script handle, 2: Comma-separated list of missing dependency handles. */
__( 'The script with the handle %1$s was enqueued with dependencies that are not registered: %2$s.' ),
$handle,
implode( ', ', $missing_dependency_handles )
);
}
}
18 changes: 18 additions & 0 deletions src/wp-includes/class-wp-styles.php
Original file line number Diff line number Diff line change
Expand Up @@ -493,4 +493,22 @@ public function reset() {
$this->concat_version = '';
$this->print_html = '';
}

/**
* Gets a style-specific dependency warning message.
*
* @since 7.0.0
*
* @param string $handle Style handle with missing dependencies.
* @param string[] $missing_dependency_handles Missing dependency handles.
* @return string Formatted, localized warning message.
*/
protected function get_dependency_warning_message( $handle, $missing_dependency_handles ) {
return sprintf(
/* translators: 1: Style handle, 2: Comma-separated list of missing dependency handles. */
__( 'The style with the handle %1$s was enqueued with dependencies that are not registered: %2$s.' ),
$handle,
implode( ', ', $missing_dependency_handles )
);
}
}
29 changes: 29 additions & 0 deletions tests/phpunit/tests/dependencies/scripts.php
Original file line number Diff line number Diff line change
Expand Up @@ -4093,4 +4093,33 @@ public function test_print_translations_no_display_no_sourceurl() {
$translations_script_data = $wp_scripts->print_translations( 'test-example', false );
$this->assertStringNotContainsStringIgnoringCase( 'sourceURL=', $translations_script_data );
}

/**
* Tests that WP_Scripts emits a _doing_it_wrong() notice for missing dependencies.
*
* @ticket 64229
* @covers WP_Dependencies::all_deps
*/
public function test_wp_scripts_doing_it_wrong_for_missing_dependencies() {
$expected_key = 'WP_Dependencies::all_deps';
$this->setExpectedIncorrectUsage( $expected_key );

wp_register_script( 'registered-dep', '/registered-dep.js' );
wp_register_script( 'main', '/main.js', array( 'registered-dep', 'missing-dep' ) );
wp_enqueue_script( 'main' );

get_echo( 'wp_print_scripts' );

$this->assertArrayHasKey(
$expected_key,
$this->caught_doing_it_wrong,
'Expected WP_Dependencies::all_deps to trigger a _doing_it_wrong() notice for missing dependency.'
);

$this->assertStringContainsString(
'The script with the handle main was enqueued with dependencies that are not registered: missing-dep',
$this->caught_doing_it_wrong[ $expected_key ],
'Expected _doing_it_wrong() notice to indicate missing dependencies for enqueued script.'
);
}
}
33 changes: 33 additions & 0 deletions tests/phpunit/tests/dependencies/styles.php
Original file line number Diff line number Diff line change
Expand Up @@ -814,4 +814,37 @@ public function test_source_url_with_concat() {

$this->assertEqualHTML( $expected, $printed );
}

/**
* Tests that WP_Styles emits a _doing_it_wrong() notice for missing dependencies.
*
* @ticket 64229
* @covers WP_Dependencies::all_deps
*/
public function test_wp_style_doing_it_wrong_for_missing_dependencies() {
$expected_key = 'WP_Dependencies::all_deps';
$this->setExpectedIncorrectUsage( $expected_key );

wp_register_style(
'main-style',
'/main-style.css',
array( 'missing-style-dep' )
);

wp_enqueue_style( 'main-style' );

get_echo( 'wp_print_styles' );

$this->assertArrayHasKey(
$expected_key,
$this->caught_doing_it_wrong,
'Expected WP_Dependencies::all_deps to trigger a _doing_it_wrong() notice for missing dependency.'
);

$this->assertStringContainsString(
'The style with the handle main-style was enqueued with dependencies that are not registered: missing-style-dep',
$this->caught_doing_it_wrong[ $expected_key ],
'Expected _doing_it_wrong() notice to indicate missing dependencies for enqueued styles.'
);
}
}
28 changes: 28 additions & 0 deletions tests/phpunit/tests/script-modules/wpScriptModules.php
Original file line number Diff line number Diff line change
Expand Up @@ -1965,6 +1965,7 @@ public function test_script_module_printing_and_dependency_ordering( bool $use_g
global $wp_version;
$wp_version = '99.9.9';

$this->setExpectedIncorrectUsage( 'WP_Script_Modules::sort_item_dependencies' );
$register = static function ( ...$args ) use ( $use_global_function ) {
if ( $use_global_function ) {
wp_register_script_module( ...$args );
Expand Down Expand Up @@ -2312,4 +2313,31 @@ public function test_static_import_dependency_with_dynamic_imports_depending_on_
"Expected script modules to match snapshot:\n$script_modules"
);
}

/**
* Tests that a missing script module dependency triggers a _doing_it_wrong() notice.
*
* @ticket 64229
* @covers WP_Script_Modules::sort_item_dependencies
*/
public function test_missing_script_module_dependency_triggers_incorrect_usage() {
$this->setExpectedIncorrectUsage( 'WP_Script_Modules::sort_item_dependencies' );

$this->script_modules->register( 'main-module', '/main-module.js', array( 'missing-mod-dep' ) );
$this->script_modules->enqueue( 'main-module' );

get_echo( array( $this->script_modules, 'print_enqueued_script_modules' ) );

$this->assertArrayHasKey(
'WP_Script_Modules::sort_item_dependencies',
$this->caught_doing_it_wrong,
'Expected WP_Script_Modules::sort_item_dependencies to be reported via doing_it_wrong().'
);

// Assert the message mentions the missing dependency handle.
$this->assertStringContainsString(
'The script module main-module was enqueued with dependencies that are not registered: missing-mod-dep',
$this->caught_doing_it_wrong['WP_Script_Modules::sort_item_dependencies']
);
}
}
Loading