PHP 8 - TypeError: Illegal offset type in isset or empty in OptionsBase.php

Created on 20 May 2022, about 2 years ago
Updated 1 March 2023, over 1 year ago

Problem/Motivation

After upgrading PHP to 8.1.5, a PHP TypeError occurred.

TypeError: Illegal offset type in isset or empty in Drupal\webform\Plugin\WebformElement\OptionsBase->getElementSelectorInputValue() (line 819 of webform/src/Plugin/WebformElement/OptionsBase.php)

Steps to reproduce

  1. Create a Webform.
  2. Add a 'radios other' element to this form
  3. Create a condition to hide the 'radios other' element created on step 2. For example, add another element and hide the 'radios other' element when the new element has a certain value.
  4. Create an email handler and set a condition for it to send an email when the 'radios other' element has a certain value'.
  5. view the webform and fill in some data to match the condition created at step 3. So that the 'radios other' element is hidden.
  6. Submit this form
  7. At this stage, the PHP fatal error occurred.

The problem is that when the php error occurred, the variable of $value in line 792 (https://git.drupalcode.org/project/webform/-/blob/6.1.3/src/Plugin/Webfo...)

 if (is_array($value) && count($value) === 2 && isset($value[$type]) && isset($value['other'])) {

is an array and the value is:
array[2]
[[other] => '', [radios] => NULL]

The value of variable $type is 'radios'.

and the function isset($value[$type]) returns false.

The reason is that, since PHP 8 the result of isset() function has been changed if a variable with null, the isset function returns false.
More explanation see https://rubus.xyz/en/blog/php-isset

That causes line 793 (https://git.drupalcode.org/project/webform/-/blob/6.1.3/src/Plugin/Webfo...)

$value = $class::processValue($element, $value);

is skipped.

That is why the line 819 (https://git.drupalcode.org/project/webform/-/blob/6.1.3/src/Plugin/Webfo...)

return (isset($options[$value])) ? $value : NULL;

throw an type error exception, because the $value is an array rather than a string.

Proposed resolution

Use array_key_exists() instead of isset() in line 792 (https://git.drupalcode.org/project/webform/-/blob/6.1.3/src/Plugin/Webfo...)

 if (is_array($value) && count($value) === 2 && isset($value[$type]) && isset($value['other'])) {

so the above should change to

if (is_array($value) && count($value) === 2 && array_key_exists($type, $value) && isset($value['other'])) {

Remaining tasks

Test script.

User interface changes

N/A

API changes

N/A

Data model changes

N/A

πŸ› Bug report
Status

Fixed

Version

6.1

Component

Code

Created by

πŸ‡¦πŸ‡ΊAustralia Mingsong πŸ‡¦πŸ‡Ί

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • πŸ‡¨πŸ‡¦Canada endless_wander

    This still causes an error for me when using the updated code from this issue. The new condition still fails and therefore this code is not run:

    $value = $class::processValue($element, $value);

    The new condition also has an illegal isset() function that returns false so I changed this:

    if (is_array($value) && count($value) === 2 && array_key_exists($type, $value) && isset($value['other']))

    to this:

    if (is_array($value) && count($value) === 2 && array_key_exists($type, $value) && array_key_exists('other', $value))

    And now the code is working if the value of $value['other'] is empty or null.

    Attached patch makes this change

  • πŸ‡¦πŸ‡ΊAustralia Mingsong πŸ‡¦πŸ‡Ί

    So, that means $value['other'] is NULL? Is my understanding right?

    Could you give more details about how to reproduce the error you came across?

  • πŸ‡¨πŸ‡¦Canada endless_wander

    Yes, $value['other'] == NULL in my scenario.

    The element looks like this:

    product_list_attached:
            '#type': radios_other
            '#title': 'Product list attached'
            '#options':
              1: 'Yes - I will attach'
            '#other__type': textarea
            '#other__option_label': 'No - explain:'
            '#other__placeholder': ''
            '#required': true
    

    In the submission triggering the error, option 1 was selected and so the $value array was:

    Array
    (
        [radios] => 1
        [other] => 
    )
    
Production build 0.69.0 2024