Problem/Motivation

Seems like some quite significant changes have been encountered in #3220021: [meta] Ensure compatibility of Drupal 9 with PHP 8.1 (as it evolves).

Steps to reproduce

Try testing D7 core with PHP 8.1

Proposed resolution

Make tests pass.

Remaining tasks

?

User interface changes

n/a

API changes

n/a

Data model changes

n/a

Release notes snippet

tbc

CommentFileSizeAuthor
#36 3224299-36_noop.patch290 bytesmcdruid
#32 3224299-31.patch21.95 KBmcdruid
#32 interdiff-3224299-29-31.txt830 bytesmcdruid
#29 3224299-29.patch21.05 KBmcdruid
#29 interdiff-3224299-27-29.txt501 bytesmcdruid
#28 3224299-27.patch20.46 KBmcdruid
#28 interdiff-3224299-24-27.txt1.09 KBmcdruid
#24 3224299-24.patch19.29 KBmcdruid
#24 interdiff-3224299-23-24.txt504 bytesmcdruid
#23 3224299-23.patch19.27 KBmcdruid
#23 interdiff-3224299-22-23.txt5.66 KBmcdruid
#22 3224299-22.patch13.01 KBmcdruid
#22 interdiff-3224299-21-22.txt663 bytesmcdruid
#21 3224299-21.patch12.39 KBmcdruid
#21 interdiff-3224299-20-21.txt456 bytesmcdruid
#20 3224299-20.patch12.39 KBmcdruid
#20 interdiff-3224299-19-20.txt913 bytesmcdruid
#19 3224299-19.patch12.4 KBmcdruid
#19 interdiff-3224299-18-19.txt2.32 KBmcdruid
#18 3224299-18.patch10.63 KBmcdruid
#16 3224299-16.patch7.22 KBmcdruid
#15 3224299-15.patch6.16 KBmcdruid
#11 3224299-11_noop.patch292 bytesmcdruid
#2 3224299-2_noop.patch281 bytesmcdruid

Issue fork drupal-3224299

Command icon 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:

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

mcdruid created an issue. See original summary.

mcdruid’s picture

noop patch for testing with PHP 8.1

andypost’s picture

Taran2L’s picture

Is there a point to add support of PHP8.1 to D7?

PHP8.0 will be supported until 26 Nov 2023 (a year after D7 end of life), also I think most D7 modules won't be updated. I see that even some of the most popular D7 modules are not updated to PHP8.0 yet.

mcdruid’s picture

re. #4, yes D7 End of Life is November 2022, but after that there will be D7 Extended Support:

https://www.drupal.org/project/d7es

I believe that's due to run another 3 years until November 2025, which is beyond when any current version of PHP is due to be supported (directly by the upstream developers at least).

heni_deepak’s picture

#6 Yes, I agree with @mcdruid
There are a lot of sites running in D7. It will take time for all the sites to be migrated to D8. Meanwhile, there are many servers that are being upgraded with PHP 8.1. Such D7 code would also need to be run in PHP 8.1.

There are also many projects that have been adapted to D7 for the admin interface and the front sites are built in some other technology. And other technologies require PHP 8.1, so the admin panel may crash.

joseph.olstad’s picture

looks like drush is the first thing that needs patching.

Gábor Hojtsy’s picture

Title: Drupal 7 and PHP 8.1 » [META] Make Drupal 7 core compatible with PHP 8.1
Category: Task » Plan

Retitle and mark as plan.

Gábor Hojtsy’s picture

Making the PHP 8.0 issue a related one rather than a parent.

mcdruid’s picture

Needed a new noop patch.

#2 suggests there may be a problem early on (perhaps with drush?) that's preventing the test suite from running at all... let's see if that's still the case.

mcdruid’s picture

This is pretty messy, but trying to grep / sed / tr the output of the failing test we can get a list of the first few issues we'll need to look at.

Something like:

curl -s https://www.drupal.org/pift-ci-job/2232718 | grep -A2 Deprecated | sed 's/\[31;40m.*$//g' | tr -d '\012\015' | sed 's#Deprecated#\nDeprecated#g' | sort | uniq

Manually tidying up the output a bit, I think we have these:

Deprecated function: mb_substr(): Passing null to parameter #1 ($string) of type string is deprecated in drupal_substr() (line 593 of /var/www/html/includes/unicode.inc).

Deprecated function: rtrim(): Passing null to parameter #1 ($string) of type string is deprecated in url() (line 2349 of/var/www/html/includes/common.inc).

Deprecated function: strlen(): Passing null to parameter #1 ($string) of type string is deprecated in drupal_http_request() (line 946 of/var/www/html/includes/common.inc).

Deprecated function: strlen(): Passing null to parameter #1 ($string) of type string is deprecated in drupal_random_bytes() (line 2268 of/var/www/html/includes/bootstrap.inc).

Deprecated function: strpos(): Passing null to parameter #1 ($haystack) of type string is deprecated in system_requirements()(line 525 of /var/www/html/modules/system/system.install).

Deprecated function: trim(): Passing null to parameter #1 ($string) of type string is deprecated in drupal_http_request() (line 1022 of/var/www/html/includes/common.inc).

Deprecated function: unserialize(): Passing null to parameter #1 ($data) of type string is deprecated in UserController->attachLoad() (line 307 of /var/www/html/modules/user/user.module).

...and also:

Deprecated function: Return type of DatabaseStatementEmpty::current() should either be compatible with Iterator::current(): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in require_once() (line 2346 of/var/www/html/includes/database/database.inc).

Deprecated function: Return type of DatabaseStatementEmpty::next() should either be compatible with Iterator::next(): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in require_once() (line 2346 of/var/www/html/includes/database/database.inc).

Deprecated function: Return type of DatabaseStatementEmpty::key() should either be compatible with Iterator::key(): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in require_once() (line 2346 of/var/www/html/includes/database/database.inc).

Deprecated function: Return type of DatabaseStatementEmpty::valid() should either be compatible with Iterator::valid(): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in require_once() (line 2346 of/var/www/html/includes/database/database.inc).

Deprecated function: Return type of DatabaseStatementEmpty::rewind() should either be compatible with Iterator::rewind(): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in require_once() (line 2346 of/var/www/html/includes/database/database.inc).

Deprecated function: Return type of DatabaseCondition::count() should either be compatible with Countable::count(): int, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in require_once() (line 1652 of/var/www/html/includes/database/query.inc).

I'd suggest we split the first batch of those into individual issues, but the second set which all relate to Database method return types could perhaps be handled in one (or maybe two) issues.

mcdruid’s picture

Filed 9 child issues, two of which are candidates for closing as duplicates if it makes sense to fix them as part of one of the other issues (I've marked those as related and commented accordingly).

mcdruid’s picture

Actually, several but not all of the child issues I spun up are covered by a couple already created by @Ayesh:

* #3241422: [PHP 8.1] Passing `null` to internal functions deprecation fixes
* #3241427: [PHP 8.1] DatabaseStatementBase and DatabaseStatementEmpty signature mismatch fixes

If we get those 2 fixed, we can close a handful of the others.

mcdruid’s picture

This patch combines the MRs from the two issues above.

Let's see if PHP 8.1 tests will run with these fixes..

mcdruid’s picture

mcdruid’s picture

$ git apply 1304.diff 1305.diff 1306.diff 3248752-2.patch 3248756-2.patch
mcdruid’s picture

mcdruid’s picture

mcdruid’s picture

mcdruid’s picture

joseph.olstad’s picture

@mcdruid, wow looking great so far! Amazing progress, dropped from 500 errors to only a handful! Very encouraging! One nit, perhaps set the default issue branch test as php 8.0 and MySQL 8 instead of php 7.3 mysql 5.7
?
just a suggestion

I just triggered php 8 and php 7.4 tests on your latest patch to make sure there's no regressions with those versions.

joseph.olstad’s picture

@mcdruid, would seem completely rational to want to commit the above changes as it will make patching easier and allow us to focus on the remaining items. Doesn't seem to cause any regressions at all if you look at the tests, still passing accross the board.

mcdruid’s picture

mcdruid’s picture

Well the PHP8.1 + sqlite pass is a pleasant surprise!

I'm guessing that means we have one or more problems in the MySQL specific code which is causing the remaining failures in that test.

Will take a closer look at that...

joseph.olstad’s picture

Wow! yes that is a pleasant surprise, appears exactly as you suggest that the remaining issues are in the MySQL specific code.

mcdruid’s picture

I'd seen this mentioned in chat a while ago but had forgotten; the MySQL problem is down to a change in the way that integers are handled.

This was addressed in D9 in #3220021-38: [meta] Ensure compatibility of Drupal 9 with PHP 8.1 (as it evolves), specifically https://git.drupalcode.org/project/drupal/-/merge_requests/937/diffs?com...

Adding that change directly to this patch just to check it works - I may spin off a new issue to commit the change...

I'm wondering whether we should make this extra connection option conditional on the PHP version. D9 doesn't but then it doesn't support PHP 5 etc.. :)

mcdruid’s picture

Looking like we're in good shape, although some tests are still re-running.

The last patch adds the new PDO attribute with a leading slash which is inconsistent with the other options. That can be fixed on commit.

Taran2L’s picture

hi @mcdruid, great job, great job!

mcdruid’s picture

I think that's everything committed and all (current) child issues marked as Fixed (including newly created #3248997: [PHP 8.1] Add PDO::ATTR_STRINGIFY_FETCHES to MySQL connection options).

I'd be surprised if there weren't more similar fixes needed in D7 core, but I believe that's core's test suite passing in PHP 8.1 with both MySQL and SQLite. We'll perhaps wait a little while before closing this issue as Fixed.

Thanks to @Ayesh for a lot of the initial work on this, and to everyone else that's contributed so far!

mcdruid’s picture

joseph.olstad’s picture

Wow thanks @mcdruid!

steinmb’s picture

Thank you @mcdruid! PHP 8.1 is official out, and all pending tests and issues looks green. Are we done?

mcdruid’s picture

We're at the point where D7's tests pass with PHP 8.1

However, it's often the case that more changes may be required in code which isn't directly exercised by core's tests.

Whether we mark this issue as Fixed or not doesn't really affect that, but I'd suggest that we leave it open for a bit longer anticipating that we're probably not quite "done" yet.

joelpittet’s picture

@mcdruid Thoughts on casting check_plain() $text variable to string?

I'm seeing this on ctools ATM, in the midst of tracking it down but thought I'd ask

exception: [Deprecated] Line 1898 of includes/bootstrap.inc:
htmlspecialchars(): Passing null to parameter #1 ($string) of type string is deprecated

EDIT: to give more context to why I ask, is that I think happening very generically in ctools, for example:

  protected function assertPluginMissingFunction($module, $type, $id, $function = 'function') {
    $func = ctools_plugin_load_function($module, $type, $id, $function);
    $this->assertEqual($func, NULL, t('Plugin @plugin of plugin type @module:@type for @function with missing function successfully failed.', array(
      '@plugin' => $id,
      '@module' => $module,
      '@type' => $type,
      '@function' =>$func,
    )));

Where one of those @ variables in t() is being passed to check_plain as either FALSE or NULL (null in this case). There are probably more places than can be counted. I could probably cast them in the test to make it pass (because I think this is testing missing plugins)

mcdruid’s picture

@joelpittet I think that sounds fine.

Ideally we'd have a separate issue for that, and a test would be the cherry on top :) (as it looks like core's tests don't trigger this yet).

joelpittet’s picture

Done #3254699: [D7 PHP 8.1] check_plain(): Passing null to parameter #1 check_plain() includes/bootstrap.inc, line 1907, thanks @mcdruid, added a test but still trying to figure out the workflow for pass/fail patch equivalent to MR...

Liam Morland’s picture

A merge request for the check_plain() fix is now RTBC including tests.

joseph.olstad’s picture

poker10’s picture

We have run into another issue with PHP 8.1 and PostgreSQL database: #3258185: [D7 PHP 8.1] Undefined array key "sequence_name" , so I am adding it also here.

poker10’s picture

poker10’s picture

Liam Morland’s picture

Core tests now pass on PHP 8.1 in Drupal 7. All the issues referred to in this issue are fixed. Is anything else needed or can this issue be marked fixed?

joseph.olstad’s picture

@Liam Morland
Core looks good for PHP 8.1, however the exif_custom module exposed a PHP 8.1 bug in file_entity, I'd appreciate a hand with it.
#3267961: file_entity - PHP 8.1 compatibility

This might expose something deeper down, might be worthwhile to have a look. I've been pushing a few contrib projects to add tests for PHP 8.0 and 8.1 this way we put core through it's paces a bit.

Liam Morland’s picture

Yes, I have PHP 8.1 testing configured on all my projects. But many don't. Mine all pass except election which is waiting for a fix to date.

What is the criteria for showing Drupal 7 as compatible with a PHP version? I don't think it requires every module to be working, just that none of the problems are in core.

poker10’s picture

Well, we are currently seeing some another PHP 8.1 deprecated warnings but these are likely caused by 3rd party modules. I do not know if it is worth fixing it on the Drupal core side (thus I have not created the issue for these yet).

Deprecated function: strlen(): Passing null to parameter #1 ($string) of type string is deprecated in drupal_validate_utf8() (line 1936 of /xxx/includes/bootstrap.inc).
Deprecated function: str_replace(): Passing null to parameter #3 ($subject) of type array|string is deprecated in filter_xss() (line 1503 of /xxx/includes/common.inc).

These are likely caused by some module sending null to filter_xss() function. We have experienced these on some ajax calls (related to admin views, or views ajax filters), but it needs more testing.

What do you think, it is worth to create Drupal core issue for these to sanitize it on the Drupal core side?

Liam Morland’s picture

In principle, they should be fixed in each module, but many modules do not get much if any maintenance now. So, it is probably more useful to fix them in core. Still, I don't think this should hold up declaring that Drupal core is compatible with PHP 8.1.

The automated testing in many modules is configured to use old versions of PHP. It would be great to automatically update these to current versions. It would also be helpful to better expose the most recent version that a module passes on.

joseph.olstad’s picture

I think the issue is, hardly anyone is using PHP 8.0 at this moment, let alone PHP 8.1. There's great reasons to want to upgrade to PHP 8.0 however I haven't yet done so (but soon yes). I have a system that can handle multiple versions of PHP but I haven't configured PHP 8.0 and PHP 8.1 on my servers yet.

With that said, I've been fixing issues related to PHP 8.0 relying on the automated test results on Drupal.org.

In time I can see contrib getting more attention as people decide to upgrade to PHP 8.0 and PHP 8.1, just give it some time.

Great work on core from @mcdruid , it's nice to have core in a good state like this. There's work to be done in contrib, not insurmountable but there's still quite a bit to do.

It would be nice if some of us could be granted special privileges to go through contrib and fix PHP 8.1 issues through many many projects. It's time consuming to go through all the processes to be able to do so. With that said, most of the projects I'm responsible for are PHP 8.0 ready and probably not much effort for PHP 8.1, I'm keeping an eye on them.

Currently I have a vestibular neuritis condition so it's been slowing me down for the past month or so. Some other issues dealing with too.

mfb’s picture

In #3254699: [D7 PHP 8.1] check_plain(): Passing null to parameter #1 check_plain() includes/bootstrap.inc, line 1907 the check_plain() input was cast to string, despite the function being documented as only accepting string - @param string $text - which I'd say sets a precedent that the same should be done for drupal_validate_utf8() and filter_xss() - which are documented as just @param $text and @param $string - i.e. accepting loosely-typed input is even more reasonable for these functions.

poker10’s picture

Thanks @mfb, good point.

I have created two PHP 8.1 deprecation issues. One was mentioned before (filter_xss() problem) and the second is a new issue which I have run into while working on fix for l10n_update module.

#3270546: [D7 PHP 8.1] str_replace(): Passing null to parameter #3 ($subject) of type array|string is deprecated in filter_xss()

#3270543: [D7 PHP 8.1] preg_split(): Passing null to parameter #2 ($subject) of type string is deprecated in _locale_parse_js_file()

poker10’s picture

There is another similar deprecation warning in text_summary() also caused by NULL input.

#3270881: [D7 PHP 8.1] strpos(): Passing null to parameter #1 ($haystack) of type string is deprecated in text_summary()

poker10’s picture

Found an issue in Simpletest module reported by @DamienMcKenna also related to the PHP 8/8.1: #3276848: run-tests.sh gives "Deprecated: str_replace(): Passing null to parameter" with PHP 8.0. It seems like an easy fix.

poker10’s picture

In addition to the last run-tests.sh issue, there is another PHP 8 issue. Patch with backport is ready, already fixed in D9: #3273723: fopen() error in stream_wrappers.inc on PHP 8

poker10’s picture

We have run into this PHP 8.1 deprecation on one windows environment: #3299271: [D7 PHP 8.1] strlen(): Passing null to parameter #1 ($string) of type string is deprecated in drupal_random_bytes(). Patch attached.

joseph.olstad’s picture

I just RTBC'd the issue 3299271 by @poker10 mentioned in comment #59. Good to go.

mpp made their first commit to this issue’s fork.

mpp’s picture

Status: Needs review » Needs work

Patch needs a reroll. Might be useful to fix this in a fork instead of using attached patches?

mpp’s picture

Rerolled the patch from #32 and opened a merge request.
Most issues have been solved in separate issues linked to this meta issue.

- In the meanwhile the int conversion fix in the color module from https://www.drupal.org/i/3248752 was reverted in https://www.drupal.org/project/drupal/issues/3249605#comment-14678206
- this issue missed one https://www.drupal.org/project/drupal/issues/3241422#comment-14678213

poker10’s picture

The change in _color_unpack() introduced a regression, so it was reverted. You now propose the same change, as was reverted - can we please know a reason for this?

I tried to run color.module tests on this change again a they failed. So if this is causing any issues in PHP 8.1, please open a new issue with the different approach to fix, as this cannot be used (does not pass tests).

The second one (missed) - I see the assertion without the conversion on two more places (instead of one), but have not experienced problems with tests until now. Are these causing any issues? I do not think we need to fix something that is working. If this is causing problems, then I think that also here we need to create a new issue so we can check that and fix.

Thanks!

poker10’s picture

Last three issues are commited.

I think we should close this as fixed and mark D7 compatible with PHP 8.1. with September release or December release. PHP 8.1. was released on 25.11.2021 and the last reported problem was in May (if I do not count the specific windows-related one). But let's wait a few days for @mpp, whether new problems will arise.

joseph.olstad’s picture

Might be some sort of test bot issue with 5.3
https://www.drupal.org/pift-ci-job/2467436

looks like maybe Mixologic might have changed something I don't see any automated test results for 7.x

https://www.drupal.org/node/3060/qa

joseph.olstad’s picture

I created a ticket in the DrupalCI: Test Runner issue queue
 #3307795: Drupal 7.x core tests dissappeared

poker10’s picture

@joseph.olstad Thanks for noticing it! We have also asked on #drupal-infrastructure slack channel what could cause this. The issues are with all D7 tests (not only PHP 5.3). I have noticed it here with the main PHP 7.4/MySQL testing: https://www.drupal.org/pift-ci-job/2467463

AndrewGearhart’s picture

Does the release yesterday of Drupal 7.92 mean that php 8.1 "compatibility" won't exist until December?

We're currently moving 7.x sites and would prefer to move to php 8.1 rather than 8.0 and then 8.1.

poker10’s picture

Status: Needs work » Active

For Drupal 7 core - currently all known PHP 8.1 issues are resolved and commited (see child issues here), so the 7.92 release should be pretty safe and stable on PHP 8.1. If we don't get any new reports about the PHP 8.1 compatibility issues in the near future, then I think we will close this issue as Fixed and announce the compatibility officially, but practically it won't change anything (it's only the announcement).

The situation with contrib modules is a bit different. You will need to carefully check which you are using a see if they made a release with PHP 8+ compatibility fixes. If not, you will need to apply patches from their issue queue manually (if there are any).

Changing the status of this issue back to Active (no work needed currently, all child issues are resolved).

heni_deepak’s picture

@Poker 10 I've been following this issue from the start and last week I updated my previous project with PHP 8.1. It's really good to know that D7 is compatible with PHP 8.1. Thank You

mpp’s picture

Same here, all our sites are tested and running on php 8.1

mcdruid’s picture

Thanks for the feedback - great to hear that real D7 sites are running on PHP 8.1 happily!

Agreed with @poker10 that we'll keep this issue open until around the end of the month (Sep '22) and if nothing significant has come up for D7 core, we'll mark it fixed.

That means that D7 does now have support for PHP 8.1, but that there may still be some problems not exercised by D7's test suite.

Contrib may be a different kettle of worms.

It'd be great if people could test their D7 sites on PHP 8.1 and raise issues for any problem with core and contrib modules.

mcdruid’s picture

Status: Active » Fixed

Seems like any new PHP 8.1 issues since the last comment are down to problems in contrib.

So let's mark this as Fixed; thank you everyone that contributed to making D7 compatible with PHP 8.1 :)

Status: Fixed » Closed (fixed)

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

mustardman’s picture

I think I found another php v8 issue when using contact form since each() has been removed in v8.

Error: Call to undefined function each() in SMTP->Data() (line 393 of /home/mywebsite/public_html/sites/all/modules/smtp/smtp.transport.inc).

This is the code at that location.

while (list(, $line) = @each($lines)) {
      $lines_out = NULL;
      if ($line == "" && $in_headers) {
        $in_headers = FALSE;
      }

UPDATE: I guess smtp is a 3rd party module and not part of core, so I guess it doesn't belong in this thread.

Anways, this is how I fixed it. There is another line a bit further down with a similar fix.

foreach($lines as $line) {
      $lines_out = NULL;
      if ($line == "" && $in_headers) {
        $in_headers = FALSE;
      }
poker10’s picture

The mentioned problem is caused by the SMTP module, see this issue: #2946667: Remove usage of deprecrated each() function for PHP 7.2+ future proofing. Unfortunatelly, it was fixed 4 year ago, but not stable release was published until today, so you will need to either download a DEV version of that module, or apply that patch manually.

mustardman’s picture

That did the trick, thanks!

joseph.olstad’s picture

ccarnnia’s picture

Just a quick thank you to all.
Your work here allows me to build new D10 sites on the same infrastructure that host legacy D7 sites.
Site by site migration and is number 1 priority but it helps to know I will not have to wait a long time to upgrade D9 sites to D10.
Thank you for making our tax dollars go further.

joseph.olstad’s picture

@ccarnnia, yes it's a win-win-win for everyone, my Drupal 7 sites are performing extremely well on PHP 8.2. Still a few minor issues to deal with on some contrib stuff but it's working well overall. I'm impressed!