Improve match (regex) condition

Created on 29 November 2023, about 1 year ago

Problem/Motivation

The "matches(/x/)" only accepts string literals. It would be nice if:

1) You could send in constants or _pseudo fields here which properly got property values from the rest of the YAML.
2) You didn't need to add the "/" delimeters, which could be an overridable default.

Both of these aid in an easier-to-read setup. Consider:

BEFORE:

process:
  _field:
    plugin: condition
    condition: matches(/\/(products|features)\//)

Note above it's hard to tell the delimeters from the escaped backslashes in the string, as well as the increased complexity with capturing groups' parenthesis () mixed in with the matches() wrapper.

AFTER:

source:
  constants:
    regex: \/(products|features)\/
process:
  _field:
    plugin: condition
    condition: matches(constants/regex)

This is much easier to parse as a human and less likely to make errors with delimiters or encapsulating parens.

✨ Feature request
Status

Active

Version

2.1

Component

Code

Created by

πŸ‡ΊπŸ‡ΈUnited States amaisano Boston

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

Comments & Activities

  • Issue created by @amaisano
  • πŸ‡ΊπŸ‡ΈUnited States amaisano Boston
  • πŸ‡ΊπŸ‡ΈUnited States danflanagan8 St. Louis, US

    Great idea, @amaisano

    For some reason, `matches` doesn't have the `property` configuration key that many condition plugins have (like `equals`, `greater_than`, etc.). I think the goal of this issue should be to add that same functionality to `matches`.

    For BC reasons, I don't think we can change the "parens" behavior in the module. However, once `property` is supported within `matches`, a hook_plugin_info_alter should allow you to change the `parens` setting in the `matches` annotation to be `property`.

    There's also some validation we'd have to change. And the `regex` key would no longer be required.

    I can't recall exactly why I didn't make the `matches` plugin extend the SimpleComparisonBase class. Maybe that would have been better.

    Anyway, we can definitely expand configuration options here but have to be careful to maintain BC.

  • Issue was unassigned.
  • πŸ‡ΊπŸ‡ΈUnited States amaisano Boston

    Found a quick, custom plugin based solution thanks to author's help:

    
    namespace Drupal\sw_migrate\Plugin\migrate_conditions\condition;
    
    use Drupal\migrate\MigrateException;
    use Drupal\migrate_conditions\Plugin\SimpleComparisonBase;
    
    /**
     * Alternate to migrate_conditions matches condition.
     *
     * Allows dynamic regex to be passed into regex() operator
     * via source and/or _pseudo_field properties.
     *
     * @MigrateConditionsConditionPlugin(
     *   id = "regex",
     *   parens = "property"
     * )
     */
    class Regex extends SimpleComparisonBase {
    
      /**
       * {@inheritdoc}
       */
      protected function compare($source, $value) {
        if (is_string($source) && !is_null($value)) {
          $regex = '/' . $value . '/';
          return (bool) preg_match($regex, $source);
        }
        else {
          throw new MigrateException('When using the regex condition, the source must be a string.');
        }
      }
    
    }
    
    
Production build 0.71.5 2024