Problem/Motivation

See discussion from #3223443-24: [policy, no patch] Process for dealing with EOL PHP versions during the Drupal 10 and future release cycles on.

Proposed resolution

  • Deprecate \Drupal::MINIMUM_SUPPORTED_PHP in favor of a methods that returns our best estimate for the given date, based on our release schedule and PHP's known (and predicted) release cycles.
  • Hardcode safe estimates in 10.0.0, and patch the methods in each minor with updated estimates.

Note that this approach only makes sense if we issue a warning on installation (rather than an error) as discussed in #2917655: [9.4.x only] Drop official PHP 7.3 support in Drupal 9.4.

Remaining tasks

TBD

User interface changes

Users on old PHP versions automatically begin seeing new informational messages or warnings on a given date, even if they are not running the latest Drupal minor.

API changes

\Drupal::MINIMUM_SUPPORTED_PHP is deprecated in favor of \Drupal\Core\PhpRequirements::minimumSupportedPhp().

Data model changes

Probably none?

Release notes snippet

The minimum supported PHP version is now set dynamically based on the predicted end-of-life date. After PHP version is no longer supported there will be a warning about unsupported PHP version but this won't prevent running, updating, or installing Drupal.

Issue fork drupal-3261447

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:

Comments

xjm created an issue. See original summary.

xjm’s picture

Assigned: xjm » Unassigned
Status: Active » Needs review
Issue tags: +Needs tests, +Needs change record, +Needs release note
xjm’s picture

Status: Needs review » Needs work
Issue tags: -Needs change record

One thing I forgot in recommendedPhp() is that we don't want to recommend (e.g.) PHP 8.3.0 on 10.0.0, even after June 2024, because 10.0.0 will never receive backports of the required PHP compatibility. So the method should check a combination of the projected recommendation date and the Drupal minor, not just the date alone.

Both methods should also include PHP 7.4+ for the Drupal 9.4 backport.

xjm’s picture

One thing I forgot in recommendedPhp() is that we don't want to recommend (e.g.) PHP 8.3.0 on 10.0.0, even after June 2024, because 10.0.0 will never receive backports of the required PHP compatibility. So the method should check a combination of the projected recommendation date and the Drupal minor, not just the date alone.

Or maybe that is overly complicated, and we should set the recommended version based on the Drupal version rather than the date. (The minimum supported version should still be date-based.)

Edit: Except the issue with that is that we don't know for sure yet whether 10.1.0 will come out in December 2022 or June 2023. (It depends on whether we get the 10.0.0 beta blockers done by mid-May or not.) Furthermore, some PHP compatibility fixes are backportable to the production branch, so 9.3 could be marked compatible in 9.3.5 or something. Maybe it's best to address the minimum supported vs. recommended PHP versions separately.

xjm’s picture

Issue summary: View changes
Status: Needs work » Needs review

Reducing scope to just the minimum supported PHP for now.

xjm’s picture

Issue summary: View changes
xjm’s picture

Status: Needs review » Needs work
xjm’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests

This has tests now and is ready for review.

xjm’s picture

Issue summary: View changes
wim leers’s picture

I like it! Very elegant 😊

xjm’s picture

Addressed most of @Wim Leers's review, aside from:

  1.    * Constructs a new PhpRequirements object.
    

    ...because our documentation standards require using the fully-qualified name with the namespace.

  2. The data provider formatting. I originally tried using array keys instead of inline comments for the scenarios, but it turned into a huge noisy mess, so just went back to an integer-keyed provider array with inline comments about the cases. If you have any other ideas for better formatting, I'm open to them; I just wasn't able to come up with anything.

wim leers’s picture

#14.1: TIL — pretty much nothing in core does that though… so I am really confused about this statement.

#14.2 +1, that's what I meant, sorry for not making it more clear.

I think this looks good, but I'd like somebody else to confirm RTBC before marking it that :)

xjm’s picture

@Wim Leers, here's the point in our coding standards about class documentation:
https://www.drupal.org/node/1354#classes

  • If you use a namespace on a class anywhere in documentation, always make sure it is a fully-qualified namespace (beginning with a backslash).
  • Immediately after an @tag (@param, @return, @var, etc.), class and interface names must always include the fully-qualified namespace.

The reasons for this are that multiple classes in different namespaces can (and do) have the same name, and that documentation is often rendered outside the context of the class file (for example, on api.d.o). So any place in core that skips that is violating a coding standard that's been in place for the past 10 years since we introduced namespacing and PSR-0. ;) Unfortunately, it's not a simple thing to write a phpcs rule for.

lauriii’s picture

Is there any value in mentioning the class name in the __construct description? For example in IDEs that information is already available:

Based on that, I'm wondering if the documentation could be just Constructs a new object.. Regardless of this, we need to also update the class description since it's using the class name without the namespace.

lauriii’s picture

StatusFileSize
new58.58 KB
xjm’s picture

Is there any value in mentioning the class name in the __construct description? For example in IDEs that information is already available:

Not everyone uses an IDE. :) But honestly I was probably just being lazy; it should describe what the object does, not say what its name is. Maybe:

Constructs an object for dynamically identifying the minimum supported PHP.

Both parts of #17 are addressed in b1fbf43.

xjm’s picture

We might need to be a little more careful about the fact that PHP considers 8.1 to be less than (not equal to) 8.1.0. See the discussion around tests being added in #3266525: MINIMUM_SUPPORTED_PHP is less than MINIMUM_PHP. At a minimum, we should have test coverage for all variants of which value has which parts.

daffie’s picture

Status: Needs review » Needs work

I am a bit out of time. Will review more later.

xjm’s picture

Issue tags: +Drupal 9.4 target

ravi.shankar made their first commit to this issue’s fork.

ravi.shankar’s picture

Resolved few threads of MR.

xjm’s picture

Ugh, merging HEAD broke the change list. I knew there was a reason I preferred to rebase it... Will try to clean that up.

xjm’s picture

Well, check this out:

  1x: version_compare(): Passing null to parameter #1 ($version1) of type string is deprecated
    1x in PhpRequirementsTest::testMinimumSupportedPhp from Drupal\Tests\Core

New deprecation in PHP 8.1. The last time it was run, PHP 8.0 was the default environment.

xjm’s picture

Status: Needs work » Needs review

I addressed the above feedback, either by making a change to the MR or replying to the comment thread wherever I thought there was a reason not to make the change. I resolved most threads but left a couple open for @daffie to review my response on those threads.

xjm’s picture

Not sure why the passing test result is not shown in the comment thread, but it's visible at the top of the issue.

wim leers’s picture

Status: Needs review » Needs work

Whew, reviewing this was quite painful because of so many tiny commits 😅 I like my (public) commit units to be one semantical change, and not literally every step along the way.

What made this worse: GitLab is so painfully slow that I've literally forgotten what I'd previously read by the time the commit loads! I ended up not reading every commit in detail after a while, and instead just making sure it was touching either PhpRequirements or PhpRequirementsTest, so I could just review those two files in detail instead.

Found a number of things in PhpRequirements, marking Needs work for that. It feels very close though!

andregp’s picture

@Wim Leers, I might be trying to teach a fish how to swim, but a tip to help on your pain would be to navigate by, lets say, 10 by 10 commits and run git diff HEAD~10..HEAD > temp.diff each time, so you don need to check each commit individually.

wim leers’s picture

Yep :) Reviewing locally is the only solution. What I was saying in #29 is that the whole point of merge requests is that it's made easier/faster to do reviews in the browser. But GitLab's poor UX does not actually achieve that.

EDIT: thanks for teaching me that expression btw! 😄

andregp’s picture

Oh, okay, that makes sense! 😅

xjm’s picture

@Wim Leers I usually use the "changes" and "overview" views to review MRs, or I select two versions to compare, and ignore the commits. For some issues, I squash before I push, but in the case of this issue I pushed like 10 things that I actually had to fix based on the bot. I probably need to add running commit checks to my workflow for my development reop; currently they are only set up in my committer clone of core. 😅 Sorry!

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

wim leers’s picture

Status: Needs work » Reviewed & tested by the community

Review

I used git diff 973ba2539764ec2036e1c2627efec7e2e2c62f1c HEAD -M5% to see what changed because neither the GitLab UI nor the default git diff behavior are helpful (they show a file being deleted and a new one being created).

Changes Lauri made:

  1. \Drupal\Core\PhpRequirements moved to \Drupal\Core\Utility\PhpRequirements — makes sense, given that this class is not going to be used like \Drupal\Core\Link or \Drupal\Core\Url or even \Drupal\Core\DrupalKernel 👍
  2. Zero state left in the PhpRequirements class. I could not put my finger on it during my earlier reviews, but now that I see the before vs after, I think this really simplified things! 👍 With no more run-time validation, but instead there is a test for that, which will still prevent invalid values for the hardcoded PHP EOL dates. Things are just as hard-coded as before, but just simpler to interact with and understand.
  3. There is now actually more validation: one extra edge case is handled: two PHP versions EOL'ing on the same date requires the older version to be listed before the newer version. 👍
  4. No changes to the absolute heart of this change: the getMinimumSupportedPhp() function. @xjm's elegant solution is untouched 😊
  5. The diffstat speaks for itself: 7 files changed, 124 insertions(+), 387 deletions(-)

All my concerns on the merge request were related to understandability — those are now all addressed.

Tests: passing even if they seem not to

100% of tests pass … except a few Nightwatch ones, which somehow cause DrupalCI to choke and not even report on test failures 🙈

In other words, #3281863: Nightwatch tests failing >50% of test runs on PHP 7.3 in 9.4.x and 9.5.x, as well as PHP 8.1 on 10.0.x strikes again:

 ✖ Tests/toolbarTest
00:46:02.599  – Change tab (5.719s)
00:46:02.599    Timed out while waiting for element <#toolbar-item-user-tray> to be present for 5000 milliseconds. - expected "found" but got: "not found" (5176ms)
00:46:02.600        at Object.Change tab (/var/www/html/core/modules/toolbar/tests/src/Nightwatch/Tests/toolbarTest.js:55:13)
00:46:02.600        at processTicksAndRejections (node:internal/process/task_queues:96:5)

I inspected https://dispatcher.drupalci.org/job/drupal_patches/130221/consoleFull and confirmed that 100% of tests are passing except for the random fails that are being looked at in #3281863.

Conclusion

🚀

lauriii credited alexpott.

lauriii’s picture

Adding credit for @alexpott for some pairing/reviewing on this earlier today.

catch’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs reroll

This needs a 10.x MR/patch.

ravi.shankar’s picture

Status: Needs work » Needs review
Issue tags: -Needs reroll
StatusFileSize
new15.74 KB
new15.74 KB

Added a patch for Drupal 10.0.x.

const DRUPAL_MINIMUM_SUPPORTED_PHP doesn't exists in file core/includes/bootstrap.inc, so changes for this file is not valid now.

lauriii’s picture

StatusFileSize
new20.33 KB

Here's a Drupal 10 patch that also removes \Drupal::MINIMUM_SUPPORTED_PHP and removes usage from \Drupal\Tests\Core\DrupalTest::testPhpConstants.

lauriii’s picture

StatusFileSize
new20.82 KB
new2.79 KB
lauriii’s picture

Issue summary: View changes
Issue tags: -Needs release note
xjm’s picture

Status: Needs review » Needs work

The recent change is incorrect. See #3265325: Raise a warning instead of an error when installing on MINIMUM_SUPPORTED_PHP. We definitely want a warning on install, not an error.

lauriii’s picture

Issue summary: View changes
Status: Needs work » Needs review

Reverted the commit. Also updated the release note 😇

tedbow’s picture

Status: Needs review » Reviewed & tested by the community

Looks great!

lauriii’s picture

StatusFileSize
new20.64 KB
new9.58 KB
alexpott’s picture

Version: 9.5.x-dev » 9.4.x-dev
Status: Reviewed & tested by the community » Fixed

Committed 2448cd3 and pushed to 9.5.x. Thanks!
Committed 11207f9 and pushed to 9.4.x. Thanks!
Committed 3412b7b and pushed to 10.0.x. Thanks!

Backported to 9.4.x because it is helpful to have deprecations in 9.4.x and the rest is new API so not risky,

  • alexpott committed 3412b7b on 10.0.x
    Issue #3261447 by xjm, lauriii, ravi.shankar, Wim Leers, alexpott,...

  • alexpott committed 2448cd3 on 9.5.x
    Issue #3261447 by xjm, lauriii, ravi.shankar, Wim Leers, alexpott,...

  • alexpott committed 11207f9 on 9.4.x
    Issue #3261447 by xjm, lauriii, ravi.shankar, Wim Leers, alexpott,...

  • xjm committed 23d4431 on 9.4.x
    Revert "Issue #3261447 by xjm, lauriii, ravi.shankar, Wim Leers,...

  • xjm committed d22061d on 9.5.x
    Revert "Issue #3261447 by xjm, lauriii, ravi.shankar, Wim Leers,...

  • xjm committed 73a5d20 on 10.0.x
    Revert "Issue #3261447 by xjm, lauriii, ravi.shankar, Wim Leers,...
xjm’s picture

Status: Fixed » Needs work

This broke PHP 7.3 in HEAD on 9.5.x and 9.4.x. Looks like we made the same mistake we made with the original change to how the constant worked, which is not testing it on the only PHP version where the API actually does something. Oops.

I reverted it from all three branches in case this is a fundamental bug in the API and not just something to do with PHP 7.3 syntax.

xjm’s picture

StatusFileSize
new20.01 KB
pingwin4eg’s picture

Seems like fails are caused by private visibility of $drupalMinimumPhp and $phpEolDates properties. ReflectionClass::getStaticPropertyValue() throws exception if a property is not public.

pingwin4eg’s picture

Ah, yes, it's a PHP bug, which seems like was fixed in 2020, but still exists in PHP 7.3.

In the test we can replace

    $reflected->getStaticPropertyValue('phpEolDates')

with

    $reflected->getStaticProperties()['phpEolDates']

and

    $reflected->setStaticPropertyValue('drupalMinimumPhp', $drupal_minimum_php);
    $reflected->setStaticPropertyValue('phpEolDates', $php_eol_dates);

with

    $prop = $reflected->getProperty('drupalMinimumPhp');
    $prop->setAccessible(TRUE);
    $prop->setValue($drupal_minimum_php);
    $prop = $reflected->getProperty('phpEolDates');
    $prop->setAccessible(TRUE);
    $prop->setValue($php_eol_dates);

or something like that.

pingwin4eg’s picture

Version: 9.4.x-dev » 9.5.x-dev
Status: Needs work » Needs review
StatusFileSize
new19.69 KB
new1.71 KB

Here's the patch with my proposed fix for D9.4 and D9.5.

I see that tests for D10 with PHP 8.1 were successful previously, so no need for this workaround.

xjm’s picture

Status: Needs review » Reviewed & tested by the community

Great research @pingwin4eg! Much less scary than it could have been.

That also means the original 10.0.x fix can still go in and won't be at any risk in the future when PHP 8.1 goes EOL. It could have been an issue in the future if it were due to the functioning of the API, because this API dynamically changes the behavior of Drupal based on the date for a given PHP version.

  • larowlan committed 6d5dc95 on 9.4.x
    Issue #3261447 by xjm, lauriii, ravi.shankar, pingwin4eg, Wim Leers,...
  • larowlan committed f78f839 on 9.5.x
    Issue #3261447 by xjm, lauriii, ravi.shankar, pingwin4eg, Wim Leers,...

  • larowlan committed 9a55cdc on 10.0.x authored by alexpott
    Issue #3261447 by xjm, lauriii, ravi.shankar, Wim Leers, alexpott,...
larowlan’s picture

Version: 9.5.x-dev » 9.4.x-dev
Status: Reviewed & tested by the community » Fixed

Committed to 9.5.x, cherry-picked to 9.4.x after confirming it was ok with @xjm given the impending beta release.

Reapplied the original patch to 10.0.x

Status: Fixed » Closed (fixed)

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

5’s picture

This change has a consequence discussed here : https://www.drupal.org/project/drupal/issues/3324058
Perhaps an adaptation to be made? Lower the level to just warning and not error?

In any case, I think the opinion of the core commiters is welcome 😉