Commit 5eb8c432 authored by Dan Flanagan's avatar Dan Flanagan Committed by Dan Flanagan
Browse files

Issue #3312705 by danflanagan8: Add a real regex condition instead of relying on callback

parent 176af946
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ Migrate Condition plugins
* is_null
* isset
* less_than
* matches
* older_than
* or ("helper" condition that can group other conditions)

+66 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\migrate_conditions\Plugin\migrate_conditions\condition;

use Drupal\migrate\MigrateException;
use Drupal\migrate\Row;
use Drupal\migrate_conditions\Plugin\ConditionBase;

/**
 * Provides a 'matches' condition.
 *
 * This condition can be used on a source string.
 *
 * Available configuration keys:
 * - regex: The regex to match against.
 * - negate: (optional) Whether the 'matches' condition should be negated.
 *   Defaults to FALSE.
 *
 * Examples:
 *
 * Search for any digit in a string
 *
 * @code
 * process:
 *   has_a_digit:
 *     plugin: evaluate_condition
 *     condition:
 *       plugin: matches
 *       regex: '/\d+/'
 *     source: source_string
 * @endcode
 *
 * @MigrateConditionsConditionPlugin(
 *   id = "matches",
 *   requires = {"regex"}
 * )
 */
class Matches extends ConditionBase {

  /**
   * {@inheritdoc}
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    // Check if the regex is valid.
    try {
      preg_match($configuration['regex'], '');
    }
    catch (\Throwable $e) {
      throw new \InvalidArgumentException("The regex {$configuration['regex']} is invalid.");
    }
  }

  /**
   * {@inheritdoc}
   */
  protected function doEvaluate($source, Row $row) {
    if (is_string($source)) {
      return (bool) preg_match($this->configuration['regex'], $source);
    }
    else {
      throw new MigrateException('When using the matches condition, the source must be a string.');
    }
  }

}
+78 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\Tests\migrate_conditions\Unit\condition;

/**
 * @coversDefaultClass \Drupal\migrate_conditions\Plugin\migrate_conditions\condition\Matches
 * @group migrate_conditions
 */
class MatchesTest extends ConditionTestBase {

  use ConditionTestValidationTrait;
  use ConditionTestEvaluateExceptionsTrait;

  /**
   * {@inheritdoc}
   */
  protected $conditionClass = 'Drupal\migrate_conditions\Plugin\migrate_conditions\condition\Matches';

  /**
   * {@inheritdoc}
   */
  protected $conditionId = 'matches';

  /**
   * Data provider for ::testConfigurationValidation().
   */
  public function providerTestConfigurationValidation() {
    return [
      [
        'configuration' => [
          'regex' => '123',
        ],
        'message' => 'The regex 123 is invalid.',
      ],
    ];
  }

  /**
   * Data provider for ::testEvaluate().
   */
  public function providerTestEvaluate() {
    return [
      [
        'source' => 'my string',
        'configuration' => [
          'regex' => '/\d+/',
        ],
        'property_value' => NULL,
        'expected' => FALSE,
      ],
      [
        'source' => 'my 123 string',
        'configuration' => [
          'regex' => '/\d+/',
        ],
        'property_value' => NULL,
        'expected' => TRUE,
      ],
    ];
  }

  /**
   * Data provider for ::testEvaluateExceptions().
   */
  public function providerTestEvaluateExceptions() {
    return [
      'Source is not a string' => [
        'source' => 123,
        'configuration' => [
          'regex' => '/abc/',
        ],
        'property_value' => NULL,
        'expected' => 'When using the matches condition, the source must be a string.',
      ],
    ];
  }

}