Hi core developers,
please provide us with a solution for the datetimeRangeYears() like in webform;

Problem/Motivation

Deprecated function: preg_match(): Passing null to parameter #2 ($subject) of type string is deprecated in Drupal\Core\Datetime\Element\DateElementBase::datetimeRangeYears()
(line 49 of core/lib/Drupal/Core/Datetime/Element/DateElementBase.php).
(line 50 of core/lib/Drupal/Core/Datetime/Element/DateElementBase.php).

The deprecated function under php 8.3 is used in core as well as in webform (#3556560) .
protected static function datetimeRangeYears($string, $date = NULL) {...

Steps to reproduce

in a fresh installed drupal 10.5.4 with php 8.3.23

Proposed resolution

look into https://www.drupal.org/project/webform/issues/3556560#comment-16339057
[$min_year, $max_year] = explode(':', $string);

The problem with this is there is no $min_year at the start of my form; $min_year will be selected and is undefined at the beginning;
so the solution from ritarshi_chakraborty is to build the array in parts like this:

// Ensure we always have two elements, even if $string is malformed.
$parts = explode(':', $string ?? '');
$min_year = $parts[0] ?? '';
$max_year = $parts[1] ?? '';

thanks, Erich

Issue fork drupal-3556851

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

enorm created an issue. See original summary.

ritarshi_chakraborty’s picture

Working on it.

ritarshi_chakraborty’s picture

Status: Active » Needs review

The remaining test failures don't appear to be related to the datetimeRangeYears() fix.

enorm’s picture

yes, you are wright; we will proof $parts[0] and $parts[1] for existent and not null - and we don't want to check the entire $string before explode();
pertect! thank you!
greetings, Erich

smustgrave’s picture

Version: 10.5.x-dev » 11.x-dev
Status: Needs review » Needs work

Fixes need to land in 11.x first. But what's the scenario where these values are missing, may require test coverage.

ritarshi_chakraborty’s picture

Status: Needs work » Needs review

Hey @smustgrave, please let me know if you want any other changes.

smustgrave’s picture

Status: Needs review » Needs work
Issue tags: +Needs steps to reproduce

Still need concrete steps as I’m not seeing this

harivansh’s picture

Assigned: Unassigned » harivansh
harivansh’s picture

StatusFileSize
new886.64 KB

Steps to Reproduce

Create a custom form that includes a datetime field.
Set both default_value and date_year_range to an empty string.

Use the following example code:

<?php

declare(strict_types=1);

namespace Drupal\my_module\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;

/**
 * Provides a My Module form.
 */
final class ExampleForm extends FormBase {

  /**
   * {@inheritdoc}
   */
  public function getFormId(): string {
    return 'my_module_example';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state): array {
    // Reproduce the bug by passing an empty string or invalid format.
    // The issue occurs when datetimeRangeYears() receives a malformed string.
    $form['date_field'] = [
      '#type' => 'datetime',
      '#title' => $this->t('Date'),
      '#date_year_range' => '',  // Empty string triggers the bug
      '#default_value' => new \Drupal\Core\Datetime\DrupalDateTime('2024-01-01'),
    ];

    $form['actions'] = [
      '#type' => 'actions',
      'submit' => [
        '#type' => 'submit',
        '#value' => $this->t('Send'),
      ],
    ];

    return $form;
  }

}

Visit the form page in the browser.

Observe the URL — the malformed date_year_range value causes the issue.
Bug screenshot

harivansh’s picture

Assigned: harivansh » Unassigned
Status: Needs work » Needs review
smustgrave’s picture

Status: Needs review » Needs work

Okay why would you do that though?

smustgrave’s picture

Issue tags: +Needs tests

Let me elaborate more. Not knocking the code snippet at all. But is it a valid scenario?

I could write faulty code that could break things and that would be on me not the system to handle.

If a valid scenario a test case should be added

oily changed the visibility of the branch 3556851-deprecated-function-pregmatch to hidden.

oily’s picture

For testing I found this: core/tests/Drupal/KernelTests/Core/Datetime/Element/DatetimeFormElementTest.php. Lines 84 to 89 seem useful.

  /**
   * Checks we have no errors on form submit.
   *
   * @legacy-covers ::validateDatetime
   */
  public function testNoErrorMetOnFormSubmit(): void {
    // No error expected when form elements have no value.

As I understand it the error in this issue occurs when one of the datetime fields is left blank? And the error occurs on form submission?

oily’s picture

Would be helpful to get 'steps to reproduce' in the IS.

harivansh’s picture

Agree with #14
I am not sure it counts as a valid scenario, but I can think of something like this. Honestly, I can't think of any other valid scenario.

    $config = $this->config('my_module.settings');
    $year_range = $config->get('date_year_range'); // Returns NULL if not set
    $form['date_field'] = [
      '#type' => 'datelist',
      '#title' => $this->t('Select Date'),
      '#date_year_range' => $year_range, // NULL triggers deprecation
    ];
    ];

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.

anybody’s picture

anybody’s picture