Problem/Motivation

Forms with States API started to behave strange after updating to PHP8.
I was able to track it back to the following code:

{%
  set classes = [
  (has_parent and ('form-actions' in attributes.class|keys or 'form-actions' in attributes.class)) ? 'js-form-wrapper',
  (has_parent and ('form-actions' in attributes.class|keys or 'form-actions' in attributes.class)) ? 'form-wrapper',
]
%}

On PHP7 the conditionals always evaluate to TRUE, even if there is no `form-actions` class or key, so the needed classes are added.
On PHP8 this is not the case anymore, so the classes are missing.
Thus, states API gets confused and instead of hiding the correct container, it was hiding the first parent element with `js-form-wrapper` class.

Proposed resolution

If/since this always evaluates to TRUE, and no issue was reported about it until now, it can be safely reverted to the way it is in core container.html.twig:

{%
  set classes = [
    has_parent ? 'js-form-wrapper',
    has_parent ? 'form-wrapper',
  ]
%}

Remaining tasks

Check if there is a reason for these conditionals and if so, implement it properly on PHP8. Otherwise revert to default.

User interface changes

None.

API changes

None.

Data model changes

None.

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

reszli created an issue. See original summary.

rembrandx’s picture

Can you confirm it's not a difference between Twig versions that is causing the issue, but that it is with the same Twig version + different PHP versions? Eg. did you compare 2 projects running on different PHP versions but have the same Twig version (or 1 project and switch PHP versions)? Knowing for sure it's PHP or Twig, will make it easier to look for what is going on and search for a robust/future-proof solution.

In theory, it should not matter which version of PHP is running, since Twig has a clearly defined way it evaluates this conditional and that should be the same way if it's PHP 7 or if it's PHP8. So if this is happening on a PHP version change, we should be able to do some specific searches in Twig/Symphony resources for a solution as this would most likely have to be a known bug or behavior change.

reszli’s picture

I was testing this with the same project, different PHP versions:

  • on master (where the condition always returns TRUE) we have PHP 7.4 and twig/twig v2.15.1
  • on staging (where the condition started to be evaluated properly) we have PHP 8.1 and twig/twig v2.15.2

there were also some core/contrib updates, but I manually rolled them back - only switching the PHP version had any effect

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

trafo’s picture

Expression 'form-actions' in attributes.class|keys is translate into this PHP code in_array('form-actions', [ 0 ], FALSE).

In PHP 7.4 in_array would return TRUE since it uses loose comparison and 'form-actions' == 0 is TRUE.
Since PHP 8.0.0 this is fixed as note in PHP doc states it: https://www.php.net/manual/en/function.in-array.php

Proposed solution is to remove keys twig filter, since it doesn't make sense.

trafo’s picture

Status: Active » Needs review