Problem/Motivation
I tried to find related issues in the meta #3220021: [meta] Ensure compatibility of Drupal 9 with PHP 8.1 (as it evolves) but failed, sorry if this is a duplicate.
I'm upgrading an inherited project into PHP8.1 and I'm seeing deprecation messages such as
Deprecated function: str_replace(): Passing null to parameter #3 ($subject) of type array|string is deprecated in Drupal\filter\Element\ProcessedText::preRenderText() (line 101 of core/modules/filter/src/Element/ProcessedText.php).
Steps to reproduce
- Create a render array of type '#processed_text' where the text value is NULL:
$build = [
'#type' => 'processed_text',
'#text' => NULL,
'#format' => 'filtered_html',
];
\Drupal::service('renderer')->renderRoot($build);Proposed resolution
This is an instance of PHP 8.1: Passing null to non-nullable internal function parameters is deprecated and if we were to use string casting null is always converted to an empty string.
To ensure #text is always treated as a string while preserving error visibility if it’s not set, the following change is recommended:
$text = (string) $element['#text'];
For an example of why this is preferable, see this demonstration.
Remaining tasks
User interface changes
API changes
Data model changes
Release notes snippet
| Comment | File | Size | Author |
|---|---|---|---|
| #63 | 3294680-63-passing_null_to_parameter.patch | 1.75 KB | cleverhoods |
Issue fork drupal-3294680
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
marcoscanoComment #3
marcoscanoComment #4
makkus183 commentedI had the same scenario, got the deprecation warning after upgrading
Drupal 9.4.4Project toPHP 8.1The patch in #2 solves the issue for me and seems like a simple and rock solid solution to me.Thx @marcoscano !
Comment #5
cilefen commentedCan someone get a stack trace to see why the value is null?
Comment #6
makkus183 commented@cliefen
It seems that in my case the cookiebot module is causing this.
Comment #7
cilefen commentedDoes this require the alpha cookiebot contributed module? It seems like there is more than one issue here.
Comment #8
marcoscanoI no longer have access to the failing scenario I had, but I agree this is likely an error condition caused by some contrib or custom code sending null in
$element['#text']. However, since that's outside of the control of\Drupal\filter\Element\ProcessedText::preRenderText(), shouldn't this method be more defensive and regardless of what is passed in, never callstr_replace()withnullas the 3rd argument?Comment #9
makkus183 commentedI agree that the solution provided in the Patch is a good, simple, minimal invasive way to make sure
str_replacegets an empty String instead of null, which solves the mentioned warning.Comment #10
cilefen commentedI think we've been pushing back in cases like this because calling code is violating APIs. But you may find a counter-example.
Comment #11
aaronpinero commentedHere is another example of this error; seems to happen as the result of viewing a node revision history(?):
Comment #12
aaronpinero commentedFor the error about which I posted, I was able to determine that the offending module is Diff, and the dev version of that module already includes a fix.
Comment #13
laura.gatesWhen digging for the Diff issue (https://www.drupal.org/project/diff/issues/3206057) as mentioned above and found https://www.drupal.org/project/drupal/issues/3043725 likely this issue is related to that.
Comment #14
laura.gatesComment #15
laura.gatesComment #16
laura.gatesI'm not sure if this is helpful - but I'm coming across this in a few different core modules. Mostly Twig, Big Pipe, Filter, and Render
Deprecated function: str_replace(): Passing null to parameter #3 ($subject) of type array|string is deprecated in Drupal\filter\Element\ProcessedText::preRenderText() (line 101 of /var/www/html/docroot/core/modules/filter/src/Element/ProcessedText.php) #0 /var/www/html/docroot/core/includes/bootstrap.inc(347): _drupal_error_handler_real(8192, 'str_replace(): ...', '/var/www/html/d...', 101) #1 [internal function]: _drupal_error_handler(8192, 'str_replace(): ...', '/var/www/html/d...', 101) #2 /var/www/html/docroot/core/modules/filter/src/Element/ProcessedText.php(101): str_replace(Array, '\n', NULL) #3 [internal function]: Drupal\filter\Element\ProcessedText::preRenderText(Array) #4 /var/www/html/docroot/core/lib/Drupal/Core/Security/DoTrustedCallbackTrait.php(101): call_user_func_array(Array, Array) #5 /var/www/html/docroot/core/lib/Drupal/Core/Render/Renderer.php(772): Drupal\Core\Render\Renderer->doTrustedCallback(Array, Array, 'Render #pre_ren...', 'exception', 'Drupal\\Core\\Ren...') #6 /var/www/html/docroot/core/lib/Drupal/Core/Render/Renderer.php(363): Drupal\Core\Render\Renderer->doCallback('#pre_render', Array, Array) #7 /var/www/html/docroot/core/lib/Drupal/Core/Render/Renderer.php(201): Drupal\Core\Render\Renderer->doRender(Array, false) #8 /var/www/html/docroot/core/lib/Drupal/Core/Template/TwigExtension.php(581): Drupal\Core\Render\Renderer->render(Array) #9 /var/www/html/docroot/sites/default/files/assets/php/twig/636d7b6cafe24_block--post-title-info.ht_U06n0dz-rc0u1rV3sxdMsZE_z/u25ot-DICSwehYRNbUjW70QyWwN9tRrBMLRoOmUHlbE.php(85): Drupal\Core\Template\TwigExtension->renderVar(Array) #10 /var/www/html/vendor/twig/twig/src/Template.php(405): __TwigTemplate_404ea349b55bb13d4e87b05e61709f78->doDisplay(Array, Array) #11 /var/www/html/vendor/twig/twig/src/Template.php(378): Twig\Template->displayWithErrorHandling(Array, Array) #12 /var/www/html/vendor/twig/twig/src/Template.php(390): Twig\Template->display(Array) #13 /var/www/html/docroot/core/themes/engines/twig/twig.engine(55): Twig\Template->render(Array) #14 /var/www/html/docroot/core/lib/Drupal/Core/Theme/ThemeManager.php(384): twig_render_template('themes/custom/g...', Array) #15 /var/www/html/docroot/core/lib/Drupal/Core/Render/Renderer.php(422): Drupal\Core\Theme\ThemeManager->render('block', Array) #16 /var/www/html/docroot/core/lib/Drupal/Core/Render/Renderer.php(201): Drupal\Core\Render\Renderer->doRender(Array, true) #17 /var/www/html/docroot/core/lib/Drupal/Core/Render/Renderer.php(157): Drupal\Core\Render\Renderer->render(Array, true) #18 /var/www/html/docroot/core/lib/Drupal/Core/Render/Renderer.php(564): Drupal\Core\Render\Renderer->Drupal\Core\Render\@closure() #19 /var/www/html/docroot/core/lib/Drupal/Core/Render/Renderer.php(158): Drupal\Core\Render\Renderer->executeInRenderContext(Object(Drupal\Core\Render\RenderContext), Object(Closure)) #20 /var/www/html/docroot/core/lib/Drupal/Core/Render/Renderer.php(172): Drupal\Core\Render\Renderer->renderPlain(Array) #21 /var/www/html/docroot/core/modules/big_pipe/src/Render/BigPipe.php(693): Drupal\Core\Render\Renderer->renderPlaceholder('callback=Drupal...', Array) #22 /var/www/html/docroot/core/modules/big_pipe/src/Render/BigPipe.php(547): Drupal\big_pipe\Render\BigPipe->renderPlaceholder('callback=Drupal...', Array) #23 /var/www/html/docroot/core/modules/big_pipe/src/Render/BigPipe.php(305): Drupal\big_pipe\Render\BigPipe->sendPlaceholders(Array, Array, Object(Drupal\Core\Asset\AttachedAssets)) #24 /var/www/html/docroot/core/modules/big_pipe/src/Render/BigPipeResponse.php(112): Drupal\big_pipe\Render\BigPipe->sendContent(Object(Drupal\big_pipe\Render\BigPipeResponse)) #25 /var/www/html/vendor/symfony/http-foundation/Response.php(381): Drupal\big_pipe\Render\BigPipeResponse->sendContent() #26 /var/www/html/docroot/index.php(20): Symfony\Component\HttpFoundation\Response->send() #27 @main.Comment #18
fathershawnWe just saw this after moving to 8.1. As I understand it, this will break in a future version of php and the fix in the patch is a correct and reasonable way to provide the correct type to the core function. Moving this to "needs review" and hoping we can move this to RTBC
Comment #19
smustgrave commentedFrom reading the comments this seems like this can be caused by contrib modules using the wrong code.
If we were to add this having test coverage would be good.
Comment #20
fathershawnI'm willing to add a test, but what would the test case be?
I think the proposed fix, a single line change, is a reasonable and least disruptive change:
$text = $element['#text'] ?? ''Other solutions that occur to me are to cast
$element['#text']to string explicitly, but we haven't been having problems with passing non-strings in general as that would likely throw an exception when the non-string was passed to str_replace().Comment #21
joseph.olstadThe patch works however I found a way to avoid using the patch.
In our case, the problem came from our custom theme code, in the exception message I saw near the top of the exception the hint: mymodule_preprocess_ds_1col
From there, I grepped (searched) through our custom code and I found the mymodule_preprocess_ds_1col function and in that function we were not validating for a null parameter
so I fixed the code as follows:
Hope this helps someone else.
Comment #22
plopescThis is still an issue in 11.x.
Even if this deprecation message is only triggered by contrib/custom code, I agree that core could be more defensive here.
Attaching new version of the patch including basic test coverage.
Comment #24
smustgrave commentedLets see what the committers think.
Thanks for the test case definitely helps this potentially getting in.
Comment #26
mtaggart@s-5.com commentedI believe the Rules module is the reason I am getting this error as well see the details here: https://www.drupal.org/project/rules/issues/3285721#comment-15186484;
I attempted patch from comment #2 (https://www.drupal.org/project/drupal/issues/3294680#comment-14597409) with no success.
Comment #27
laura.gatesI patched #2 with drupal 10.1.3 and I so far haven't come across this error message in my logs.
Comment #28
nicolas bouteille commentedPatch #2 solves it for me when using Twig Tweaks filter {{ $some_value | check_markup('restricted_html') }} if $some_value is null.
Thanks!
Comment #29
sanduhrsPatch is working and looks reasonable to me.
Comment #30
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue.
While you are making the above changes, we recommend that you convert this patch to a merge request. Merge requests are preferred over patches. Be sure to hide the old patch files as well. (Converting an issue to a merge request without other contributions to the issue will not receive credit.)
Comment #32
ruslan piskarovI can't create new branch for 11.x-dev.
Comment #35
sudishth commentedComment #36
smustgrave commentedJust fyi #22 still cleanly applied
Going off the issue summary this needs to be answered.
Comment #37
blb commentedI see the same error.
Comment #38
arora.shivani commentedHello, I have created a patch for it. Please review.
Thank you!
Comment #39
smustgrave commentedCan the question in the proposed solution be answered please.
Comment #40
jedgar1mx commented#2 works with
10.2.6Comment #41
amitrawat056 commentedI encountered the same issue. #38 works for me, Drupal 10.2.6.
Comment #42
plopescComment #43
plopescComment #44
plopescAdded steps to reproduce and MR is still valid. Moving to NR
Comment #45
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #46
plopescMR is back to green after merging 11.x again.
Comment #49
smustgrave commentedHiding patches as fix is in MR.
Ran test-only feature
Not sure if something should be done to address '#text' => NULL, being allowed but current solution does fix the problem.
Comment #50
alexpottIdeally this would be better fixed in calling modules. It's only triggering a deprecation so we have time to fix it. But if we are going to fix it in core then we should not do so in way that hides the warning if you don't have #text set at all. See comment on MR.
Comment #52
shalini_jha commentedI Have addressed the feedback also checked the https://3v4l.org/UuKsj and re-ran the test and its is working as expected. pipeline is also green so moving this NR.
Kindly review.
Comment #53
smustgrave commentedAppears to be open thread in MR, proposed solution should be tweaked some too.
Comment #54
shalini_jha commentedComment #55
shalini_jha commentedThanks for the review , i have address the feedback as $build['#markup'] is empty string so again no need to add type cast for this . also tried to update the proposed solution according the changes we have added. Kindly review.
Comment #56
shalini_jha commentedmoving this for NR.
Comment #57
smustgrave commented1 open thread with a good suggestion.
Comment #58
shalini_jha commentedI have reviewed the suggestions provided in this MR and tested the non-convertible value case. It appears that the previous solution didn't work as expected. To address this, I made some adjustments to the $text logic to handle both scenarios correctly.
Additionally, I’ve added an extra assertion to account for the object case, ensuring that both scenarios are now properly handled. Please take a look and let me know if this approach makes sense.
Moving this to NR.
Comment #59
smustgrave commentedBelieve feedback has been addressed here.
Comment #60
catchI don't understand why serialize() is being used here and there doesn't appear to be an explanation either in the MR or the issue summary - can't think of any situation where we'd want to do that either.
Comment #61
damienmckennaFYI I ran into a similar problem and realized that ProcessedText::preRenderText() was doing a whole load of work if the string was blank, which seemed unnecessary: #3554602: Return early in preRenderText() if text is blank
Comment #63
cleverhoods commentedAdding the file here as well for composer patching.