Problem/Motivation

We are experiencing multiple deprecation warnings on PHP 8.1 in the text_summary() function:

Deprecated function: strpos(): Passing null to parameter #1 ($haystack) of type string is deprecated in text_summary() (line 358 of /modules/field/modules/text/text.module).
Deprecated function: mb_strlen(): Passing null to parameter #1 ($string) of type string is deprecated in drupal_strlen() (line 482 of /includes/unicode.inc).

The first one is directly in text_summary() and the second one is in drupal_strlen() function which is called by text_summary().

The problem is not the Drupal core itself, but some modules seems to be calling text_summary() with null, which results in this warning. I can point out at Metatag module trying to generate node tokens, but it seems like this is not the only one module causing this. This will happen when there is a node with a text_with_summary field type and this field has a null value. Some modules are directly using this null value (like Metatag module) and it will end up with this deprecation warnings.

A im posting this as a Drupal core issue, because in some other issues we went the way of sanitizing it on the Drupal core side, as multiple modules can cause this. See the recent check_plain() fix: #3254699: [D7 PHP 8.1] check_plain(): Passing null to parameter #1 check_plain() includes/bootstrap.inc, line 1907

Steps to reproduce

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

Comments

poker10 created an issue. See original summary.

poker10’s picture

Status: Active » Needs review
StatusFileSize
new646 bytes

Because there are multiple calls in text_summary() which can potentially cause deprecation warnings if $text will be null I chose the way of returning the empty $text at the very beginning if it is empty.

mfb’s picture

This patch changes how buggy code would be handled: currently text_summary(array()) throws a TypeError (on PHP 8.0), but with this patch it would return array(). That's probably not a big deal, but it might be preferable to be conservative and use is_null() logic..

poker10’s picture

StatusFileSize
new646 bytes

Yes, that is a good point, thanks. It will be better to focus only on the NULL issue in the patch and don't change behavior for other possible variable types. I am attaching updated patch.

mcdruid’s picture

Would like to see a test along with the patch ideally.

poker10’s picture

StatusFileSize
new584 bytes
new1.2 KB

Adding test.

mcdruid’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: +Pending Drupal 7 commit

Excellent, thanks!

fabianx’s picture

Assigned: Unassigned » mcdruid

RTBC + 1, approved for Merge! Thanks all!

  • mcdruid committed 45839ad on 7.x
    Issue #3270881 by poker10, mfb: PHP 8.1 strpos(): Passing null to...
mcdruid’s picture

Assigned: mcdruid » Unassigned
Status: Reviewed & tested by the community » Fixed
Issue tags: -Pending Drupal 7 commit

Thanks!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

greg boggs’s picture

I got this warning in Drupal 9 as well when I set the homepage node path to /. Should I make a separate ticket for that or do we use this one and assign it to 9x?

mcdruid’s picture

I believe the policy is to create separate tickets these days.

drupal_developer2022’s picture

Salut. Est ce que tu as trouvé une solution à propos de cette erreur dans le D9?

cilefen’s picture

gbirch’s picture

I understand that this precise issue is fixed, but the underlying problem with drupal_strlen() can be caused by many other things. Would it not be better for drupal_strlen() to return 0 if the $text is NULL?

I.e. add the following to drupal_strlen():

if (is_null($text)) {
  return 0;
}
poker10’s picture

@gbirch, there are lot of functions where your mentioned approach could be used, if we decide to go this way (drupal_strtoupper(), drupal_strtolower(), ...). But preferably we try to fix reported issues where they originated. We have made few exceptions in functions, where multiple contrib modules (and probably also core modules) were sending NULL instead of a string data. But the official policy for core is not babysit broken contrib code.

I am not sure if there are any open issues about the drupal_strlen() PHP 8 warning somewhere (except this fixed one). If yes, we can check the issue and the root cause of the problem and decide about the fix. If not, then I am not sure about fixing something, that is not an issue now. Thanks!

gbirch’s picture

@poker10, I don't think I agree with you about which code is "broken".

Prior to PHP 8, you could happily pass NULL to these functions in place of empty strings. The drupal_ functions you mention do not specify that the input must be a string in the PHP doc or otherwise. If they don't, then arguably the bug/incompatibility is in the drupal_ functions themselves, which don't behave as they used to, and not in the "broken" contrib code that uses them.

If you have been calling one of these functions in your custom/contrib code, how would you know that you must pass a string, if a) previously the functions accepted NULL values happily and b) now they don't, if the function signatures are unchanged? And from a purely practical point of view, what happens here is that the core code throws notices, and you don't immediately know what code called it without analyzing the back-trace. This is not a developer friendly result.

Finally, the whole POINT of those functions is to provide a wrapper around different PHP implementations, character sets, etc. This would be just one more compatibility wrapper.

poker10’s picture

The documentation of the drupal_strlen() function is as follows:

/**
* Counts the number of characters in a UTF-8 string.
*
* This is less than or equal to the byte count.
*
* @param $text
* The string to run the operation on.
*
* @return integer
* The length of the string.
*
* @ingroup php_wrappers
*/

So it specifies, that the input has to be a string (in the parameter description), but it is not enforced like in D10. So yes, you were able to pass NULL to these functions prior to PHP 8 without problems, but only because the underlaying strlen() function allowed that. Here are the reasons for this change in PHP: https://php.watch/versions/8.1/internal-func-non-nullable-null-deprecation.

Finally, the whole POINT of those functions is to provide a wrapper around different PHP implementations, character sets, etc. This would be just one more compatibility wrapper.

Yes, this is true. But as I have mentioned earlier, we cannot fix non-existing problems. So either there is an open issue about another problem with drupal_strlen() in PHP 8+, and we can take a look at options here, or someone need to create such issue, so that we can consider this change. We are not going to do anything else in this issue, as it is closed (fixed). Thanks!

poker10’s picture

@gbirch There is a new issue #3362238: _form_validate sends null to drupal_strlen triggering deprecation notice, which looks valid and we can discuss the potential global fix for drupal_strlen() there. Thanks.