Make WordPress Core

Opened 5 months ago

Closed 2 months ago

Last modified 2 months ago

#59832 closed defect (bug) (worksforme)

Deprecation warnings for resulting from a call to plugin_dir_url

Reported by: geistesblitzer's profile geistesblitzer Owned by:
Milestone: Priority: normal
Severity: normal Version: 6.4.2
Component: Plugins Keywords:
Focuses: Cc:

Description

The function plugin_dir_url( $file ) calls plugins_url with an empty string as the $path parameter. This in turn leads to two PHP 8.1 deprecation warnings:

Deprecated: str_replace(): Passing null to parameter #3 ($subject) of type array|string is deprecated in <path>/wp-includes/functions.php on line 2187

Deprecated: strpos(): Passing null to parameter #1 ($haystack) of type string is deprecated in <path>/wp-includes/functions.php on line 7241

Both warnings can, e.g., be seen when using the ACF Pro plugin and making a call to get_field(). While these warnings result from a function call from the plugin, the problem lies within WordPress core, as these core functions cannot be used without producing deprecation warnings.

Change History (6)

This ticket was mentioned in Slack in #core by jorbin. View the logs.


5 months ago

#2 @hellofromTonya
5 months ago

Reproduction Report

This report validates if the issue can be reproduced.

Environment

Actual Results

  • ✅ Passing __FILE__ to plugin_dir_url() returns http://wpdev.local/wp-content/mu-plugins/ with no deprecation raised.
  • ✅ Passing an empty string to plugin_dir_url() returns http://wpdev.local/wp-content/mu-plugins/ with no deprecation raised.
  • ✅ Passing 2 empty strings to plugins_url() returns http://wpdev.local/wp-content/mu-plugins/ with no deprecation raised.
  • ✅ Passing an empty string to wp_normalize_path() returns an empty string with no deprecation raised.
  • ❌ Passingnull to plugin_dir_url() returns http://wpdev.local/wp-content/mu-plugins/ but also raises both deprecation notices:
Deprecated: strpos(): Passing null to parameter #1 ($haystack) of type string is deprecated in ../wp-includes/functions.php on line 7241

Deprecated: str_replace(): Passing null to parameter #3 ($subject) of type array|string is deprecated in ..c/wp-includes/functions.php on line 2187
  • ❌ Passingnull to wp_normalize_path() returns an empty string and also both deprecation notices:
Deprecated: strpos(): Passing null to parameter #1 ($haystack) of type string is deprecated in ../wp-includes/functions.php on line 7241

Deprecated: str_replace(): Passing null to parameter #3 ($subject) of type array|string is deprecated in ..c/wp-includes/functions.php on line 2187

Additional Notes

Cannot reproduce the reported issue when passing empty strings. Though null does raise the deprecations, both functions require a string and are not nullable.

#3 @hellofromTonya
5 months ago

  • Milestone Awaiting Review deleted
  • Resolution set to invalid
  • Status changed from new to closed

Hello @geistesblitzer,

Welcome to WordPress Core's Trac :) Thanks for the report.

The function plugin_dir_url( $file ) calls plugins_url with an empty string as the $path parameter.

To test what happens when passing an empty string to the $path, I set up a must-use plugin that invokes the functions in question. Results:

  • Passing an empty string does not raise the deprecations.
  • Passing null does raise both deprecations.

Something is passing null when it should be passing a string. The functions do require a string for the $path, i.e. null is not valid input for these functions.

Looking more closely at the deprecations, both are indicating that null was passed instead of a string:

Deprecated: strpos(): Passing null to parameter #1 ($haystack) of type string is deprecated in <path>/wp-includes/functions.php on line 7241

Indicates the value passed $path when wp_is_stream() is invoked is null.

Deprecated: str_replace(): Passing null to parameter #3 ($subject) of type array|string is deprecated in <path>/wp-includes/functions.php on line 2187

Indicates the value passed to $path when invoking wp_normalize_path() is also null.

Likely a plugin, theme, and/or must-use script is invoking wp_normalize_path() or a function that invokes it and passing a null rather than with a string.

ACF Pro plugin and making a call to get_field()

You identify the deprecation gets raised when ACF's get_field() is invoked. Next step would be to reach out to ACF on their support forum https://wordpress.org/support/plugin/advanced-custom-fields/.

Other ways to troubleshoot:

  • Do a full backtrace to determine the call stack.
  • Use tracking tools such as Xdebug to step through the code to find what could be passing null to one of these functions.

I'll close this ticket as the issue appears to be code outside of Core that passing null instead of string. If after further investigation the root cause appears to be within Core itself, please reopen this ticket and provide the information gathered to help contributors continue their investigation. Thank you :)

#4 @charlestonsw
2 months ago

  • Resolution invalid deleted
  • Status changed from closed to reopened
  • Version changed from 6.4 to 6.4.2

User Story
Determining the fully qualified URL of a must-use plugin main loader file is necessary to build future links within the app.

Use Case
After plugins have been loaded set the URL:

mu-plugins/pluginname/pluginname.php

defined( 'SLPLUS_FILE' )
define( 'SLPLUS_FILE', FILE ); set the file to full path of running code

mu-plugins/pluginsname/include/otherclass.php

defined( 'SLPLUS_PLUGINURL' )
define( 'SLPLUS_PLUGINURL', plugins_url( , SLPLUS_FILE ) );

Result with PHP 8.2.3 - PHP deprecated warning "null passed".

Call Stack

plugins_url( , <fully_qualified_filename> )
wp_normalize_path(
)
wp_is_stream( )

Possible Resolutions

A) Remove optional status on first param of plugins_url()

plugins_url() has the first optional parameter set to a default of . This will fail with the above warning if no parameters are passed.

Make first param required. Not desired, will break backwards compatibility.

Make first param required only if second param is present. Not desired, will break backwards compatibility.

Fire "doing it wrong" if second param is set but not first param.

B) wp_normalize_path() modify processing if incoming path is

Skip wp_is_stream() test if path is :

if ( ($path !== ) && wp_is_stream( $path ) ) {

list( $wrapper, $path ) = explode( ':', $path, 2 );

$wrapper .= ':';

}

C) wp_is_stream() short circuit if path is empty string

At start of wp_is_stream add:
if ( $path === ) { return false; }

or is_null($path) or empty($path) -- the above matches the specificity if the real world situation.

#5 @charlestonsw
2 months ago

plugins_url() allows the first param to be optionally set to (the default) which throws this warning for PHP 8.2.3 (probably any PHP 8 version).

Plugin or theme developers SHOULD be developing with WP_DEBUG on, which then throws this error fairly early in most instances. In my case trigger a stack of "headers already sent" messages.

IMO WordPress Core function defaults should not lead to PHP warnings for supported/recommended versions of PHP. At the very least the plugins_url() should be added to the exceptions list here for PHP 8.0/8.1 etc.:
https://make.wordpress.org/core/handbook/references/php-compatibility-and-wordpress-versions/

Version 0, edited 2 months ago by charlestonsw (next)

#6 @charlestonsw
2 months ago

  • Resolution set to worksforme
  • Status changed from reopened to closed
Note: See TracTickets for help on using tickets.