Problem/Motivation

When using the Scanner module with the "Use regular expressions in search" option enabled, replacing an HTML link can result in unexpected behavior.

For example, replacing the following HTML:

<a href="https://superman.com">superman</a>

with:

<a href="https://wonderwoman.com">wonderwoman</a>

does not work as expected when regular expression search is enabled.

Scanner reports:

Found 0 matches across * entities.

However, if the Replace operation is then performed, the entire content of the affected field can be removed.

The same replacement works as expected when "Use regular expressions in search" is disabled.

This is particularly concerning because a search that reports zero matches should not result in the existing field content being cleared during the replacement operation.

The issue was reproduced using Scanner 2.0.1.

Steps to reproduce

  1. Install and enable Scanner 2.0.1.

  2. Have an entity with a text/long text field containing the following HTML:

    <a href="https://superman.com">superman</a>
  3. Open Scanner's Search and Replace functionality.

  4. Enter the following value in the Search field:

    <a href="https://superman.com">superman</a>
  5. Enter the following value in the Replace field:

    <a href="https://wonderwoman.com">wonderwoman</a>
  6. Enable "Use regular expressions in search".

  7. Run the search.

  8. Scanner reports:

    Found 0 matches across * entities.
  9. Proceed with the Replace operation.

  10. Observe that the affected field content can be completely removed instead of remaining unchanged.

Expected result:

If Scanner reports zero matches, the original field content should remain unchanged. If the supplied regular expression is invalid or cannot be matched, Scanner should report an appropriate validation/error message and should not modify the field.

Actual result:

Scanner reports zero matches, but proceeding with the Replace operation can result in the entire field content being removed.

Comparison:

When "Use regular expressions in search" is disabled, the same HTML search and replacement works as expected.

The following:

<a href="https://superman.com">superman</a>

is correctly replaced with:

<a href="https://wonderwoman.com">wonderwoman</a>

Proposed resolution

Remaining tasks

User interface changes

API changes

No API changes are proposed.

Data model changes

Issue fork scanner-3627410

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

someshver created an issue. See original summary.

andres alvarez made their first commit to this issue’s fork.

andres alvarez’s picture

Confirmed the root cause. Entity::buildCondition() builds the PHP pattern as '/' . $search . '/' from the raw user regex. An unescaped / (any URL or closing tag) ends the pattern early, which is why the search reports 0 matches. In replace(), preg_replace() returns NULL for that pattern and the NULL is saved back, leaving the field empty. The same applies to "Preceded by" / "Followed by" in regex mode.

The change escapes unescaped / in search, preceded and followed when regex is enabled (already escaped ones are left alone), and makes replace() keep the original text when preg_replace() fails, so an invalid pattern can no longer clear a field.

Added a Kernel test reproducing the reported case. It fails without the change (the field ends up NULL) and passes with it; the full module suite passes (47 tests) and the MR pipeline is green. MR opened.

andres alvarez’s picture

Status: Active » Needs review