Set field value does not set trimmed token

Created on 28 August 2023, 10 months ago
Updated 9 March 2024, 4 months ago

Problem/Motivation

I wanted to create a process that will trim spaces in a user profile fields.

First, I figured out that the "trim" option of the "Entity: set field value" had no effect.

So I prepared an intermediate action using tamper trim. The resulting token is ok when displaying with a message.

But when using the resulting token as new field value, I figured out that the replaced token was not trimmed.

BUT, when putting a character after it, for example: "[trimmed_title].", then the token was effectively trimmed...

Note: I tried to inspire myself from: https://ecaguide.org/library/test%20models/set_field_values/ to see that it was possible to change field values without having to set "Save the entity" to true.

Steps to reproduce

I attached 2 process acting on node title so no dependencies.

Proposed resolution

I have not figured out from where this is coming from and I bet maintainers of ECA will found way quicker than me.

Remaining tasks

Find a solution
Implement it

🐛 Bug report
Status

Fixed

Version

2.0

Component

Code

Created by

🇫🇷France Grimreaper France 🇫🇷

Live updates comments and jobs are added and updated live.
  • Needs tests

    The change is currently missing an automated test that fails when run with the original code, and succeeds when the bug has been fixed.

Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @Grimreaper
  • 🇩🇪Germany jurgenhaas Gottmadingen

    This is caused by what was implemented in #3261414: Add or remove a value or values from a multi-value field where ECA aims to only update field values, and consequently save entities, when they have actually changed. The code section looks like this:

            if (is_string($current_value)) {
              // Extra processing is needed for strings, in order to prevent false
              // comparison when dealing with values that are the same but
              // encoded differently.
              $current_value = nl2br(trim($current_value));
            }
    
            foreach ($values as $i => $value) {
              $new_value = !is_array($value) ? $value : (array_key_exists($property_name, $value) ? $value[$property_name] : reset($value));
              if (is_string($new_value)) {
                $new_value = nl2br(trim($new_value));
              }
              if (((is_object($new_value) && $current_value === $new_value) || ($current_value == $new_value)) && !isset($existing[$i]) && !in_array($k, $existing, TRUE)) {
                $existing[$i] = $k;
              }
              if (($i === $k) && is_array($value) && is_array($current_item) && (reset($method_settings) === 'set')) {
                $values[$i] += $current_item;
              }
            }
    

    For string values, both the current and the new value get trimmed before comparison. That means in this use case that ECA always believes that the title hasn't changed if it only gets trimmed. When removing the trimming before comparison, then both methods from @Grimreaper (trimming title directly or through the tamper trim plugin) do work as expected. But that would cause other changes, that are probably unintended.

    @mxh, do you have any idea how we can resolve this?

  • 🇩🇪Germany mxh Offenburg

    One possible way I currently see is to add a new value for the "Method" option called "Set and enforce clear previous value" set:force_clear where force_clear empties the arrays before set is being applied:

    // ...
    switch ($method_setting) {
    
              case 'force_clear':
                $keep = $existing = $current_values = [];
                break;
    
              case 'clear':
    // ...
    
  • Assigned to jurgenhaas
  • 🇩🇪Germany jurgenhaas Gottmadingen
  • Issue was unassigned.
  • Status changed to Needs review 4 months ago
  • 🇩🇪Germany jurgenhaas Gottmadingen

    I've now implemented the suggested solution from @mxh which needs a review. But we also need to write a test for this.

  • Pipeline finished with Success
    4 months ago
    Total: 400s
    #101229
  • First commit to issue fork.
  • 🇩🇪Germany danielspeicher Steisslingen

    I have added a test for force_clear. Looks good. I also added a return type in SetFieldValue.php

    Please review and set issue to fixed if everything is ok.

  • Pipeline finished with Failed
    4 months ago
    Total: 372s
    #102378
  • Status changed to Needs work 4 months ago
  • 🇩🇪Germany jurgenhaas Gottmadingen

    Looked at the test and I think it doesn't actually test the problem why this fix got introduced: it's about trimming a field value.

    Example: if the node title is my title with one or many spaces at the beginning and/or end of the string, and the use wants to replace that title with the trimmed version my title, then the set:clear function does NOT work, but the set:force_clear does.

    So, we should have tests that confirm, for that case, that one mode works and the other doesn't.

    Apart from that, there is a code style issue and the change of return type in modules/content/src/Plugin/Action/SetFieldValue.php is probably off-topic, and we may want to go through such smells (that are not reported by PHPCS or PHPStan) in a separate issue, if at all. I'm not sure how certain PHP versions behave if interfaces and subclasses have different notations of the same method.

  • 🇩🇪Germany danielspeicher Steisslingen

    Thanks for that hint. I will update the test. You are right, we should tackle this in another issue, but it is hard for me to ignore those smells.

  • Pipeline finished with Canceled
    4 months ago
    Total: 83s
    #102551
  • Pipeline finished with Failed
    4 months ago
    Total: 379s
    #102552
  • Pipeline finished with Failed
    4 months ago
    Total: 460s
    #102556
  • 🇩🇪Germany danielspeicher Steisslingen

    I wrote a new test function testNodeTitleForceClear. As for as I understand your example above: The test creates a node with the title my title and the action sets the title to my title.

    Whether the clear nor the force_clear works. See the failed test. Please take a look if the test is appropriate. If not, please adapt.

    After debugging conditionally, the test is correct.:

    In FiledUpdateActionBase the currentValue and the newValue get trimmed anyway. Line 280 and line 286. So line 289 gets executed and the this causes the function to jump out of the loop in line 298, because the arrays have the same size.

    The method setting switch case gets never executed.

  • Pipeline finished with Success
    4 months ago
    Total: 369s
    #103040
  • Status changed to Needs review 4 months ago
  • 🇩🇪Germany jurgenhaas Gottmadingen

    I've checked the method in FieldUpdateActionBase and realized that the Create a map of indices that refer to the already existing counterpart. part should only be executed if the method is NOT force_clear. That makes it work correctly and also fixed the test written by @danielspeicher in #11

    Then, I've also added another test in the same method, that ensures that the method clear does NOT change the field value.

    While being in that part of the code, I remove the nested ternary structures as they are difficult to read and should ever be used in PHP.

  • Status changed to RTBC 4 months ago
  • 🇩🇪Germany danielspeicher Steisslingen

    Cool. Think that will work now perfecly.

  • Pipeline finished with Skipped
    4 months ago
    #103054
  • Pipeline finished with Skipped
    4 months ago
    #103055
    • jurgenhaas committed f371c6f9 on 2.0.x
      Issue #3383905 by danielspeicher, jurgenhaas, Grimreaper, mxh: Set field...
  • Status changed to Fixed 4 months ago
  • 🇩🇪Germany jurgenhaas Gottmadingen

    Great, thank you.

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

  • Pipeline finished with Success
    3 months ago
    Total: 213s
    #141985
  • Pipeline finished with Success
    3 months ago
    Total: 214s
    #142008
  • Pipeline finished with Success
    3 months ago
    Total: 217s
    #142633
  • Pipeline finished with Success
    3 months ago
    Total: 277s
    #143353
  • Pipeline finished with Success
    3 months ago
    Total: 240s
    #143770
  • Pipeline finished with Success
    3 months ago
    Total: 210s
    #143778
  • Pipeline finished with Success
    3 months ago
    Total: 182s
    #143781
  • Pipeline finished with Success
    3 months ago
    #143792
  • Pipeline finished with Success
    3 months ago
    #143898
  • Pipeline finished with Success
    2 months ago
    Total: 242s
    #151384
  • Pipeline finished with Success
    about 2 months ago
    Total: 373s
    #161964
  • Pipeline finished with Skipped
    about 2 months ago
    #162784
  • Pipeline finished with Success
    about 1 month ago
    Total: 246s
    #183567
Production build 0.69.0 2024