From bf8eb10cb4f9877a7970470e4ea8b34af91a8d0a Mon Sep 17 00:00:00 2001
From: Axel Rutz <axel.rutz@clever-systems.net>
Date: Mon, 8 Jul 2013 01:15:55 +0200
Subject: [PATCH 1/2] Issue #1658092: Added Action: Regular Expression.

---
 modules/data.eval.inc  |   10 ++++++++++
 modules/data.rules.inc |   34 ++++++++++++++++++++++++++++++++++
 tests/rules.test       |   18 ++++++++++++++++++
 3 files changed, 62 insertions(+)

diff --git a/modules/data.eval.inc b/modules/data.eval.inc
index bbeddfa..fe18fb7 100644
--- a/modules/data.eval.inc
+++ b/modules/data.eval.inc
@@ -89,6 +89,16 @@ function rules_action_data_calc($input1, $op, $input2, $settings, $state, $eleme
   }
 }
 
+
+/**
+ * Action: Regular expression.
+ */
+function rules_action_data_regex($string, $expression, $settings, $state, $element) {
+  preg_match_all($expression . 'u', $string, $matches);
+  $result = isset($matches['result']) ? $matches['result'] : $matches[0];
+  return array('result' => $result);
+}
+
 /**
  * Info alter callback for the data_calc action.
  */
diff --git a/modules/data.rules.inc b/modules/data.rules.inc
index e78420b..6ca1def 100644
--- a/modules/data.rules.inc
+++ b/modules/data.rules.inc
@@ -73,6 +73,40 @@ function rules_data_action_info() {
       ),
     ),
   );
+  $return['data_regex'] = array(
+    'label' => t('Search for matches using a regular expression.'),
+    'group' => t('Data'),
+    'base' => 'rules_action_data_regex',
+    'parameter' => array(
+      'string' => array(
+        'type' => 'text',
+        'label' => t('String'),
+        'description' => t('The string on which to run the regular expression.'),
+      ),
+      'expression' => array(
+        'type' => 'text',
+        'label' => t('Expression'),
+        'description' => t('The <a href="@regex">regular expression</a> to search for, with enclosing <a href="@delimiters">delimiters</a> and maybe <a href="@modifiers">modifiers</a>, as a string.  The "u" (unicode) modifier is always appended. Tip: <a href="@RegExr">RegExr: Online Regular Expression Testing Tool</a> is helpful for learning, writing, finding, and testing Regular Expressions.',
+          array(
+            '@regex' => 'http://www.php.net/manual/en/reference.pcre.pattern.syntax.php',
+            '@delimiters' => 'http://www.php.net/manual/en/regexp.reference.delimiters.php',
+            '@modifiers' => 'http://www.php.net/manual/en/reference.pcre.pattern.modifiers.php',
+            '@RegExr' => 'http://gskinner.com/RegExr/',
+          )
+        ),
+        'default value' => '/.*/',
+      ),
+    ),
+    'provides' => array(
+      'result' => array(
+        'type' => 'list<text>',
+        'label' => t('Result'),
+        'description' => t('The results of the search as list of strings. If the regular expression contains a <a href="@subpatterns">subpattern</a> named "result", this will be taken, otherwise the whole match.',
+            array('@subpatterns' => 'http://www.php.net/manual/en/regexp.reference.subpatterns.php')),
+      ),
+    ),
+    // @todo validate expression via @preg_match($e, null) === false
+  );
   $return['list_add'] = array(
     'label' => t('Add an item to a list'),
     'parameter' => array(
diff --git a/tests/rules.test b/tests/rules.test
index 0cc10b6..9956021 100644
--- a/tests/rules.test
+++ b/tests/rules.test
@@ -1475,6 +1475,24 @@ class RulesIntegrationTestCase extends DrupalWebTestCase {
     $result = rules_condition('text_matches')->execute('my-text', 'me?y-texx?t', 'regex');
     $result2 = rules_condition('text_matches')->execute('my-text', 'me+y-texx?t', 'regex');
     $this->assertTrue($result && !$result2, 'Text matching condition using operation regex evaluated.');
+
+    // Test action: Search for matches using a regular expression
+    $action_set = rules_action_set(array(
+      'string' => array('type' => 'text', 'label' => 'String'),
+      'expression' => array('type' => 'text', 'label' => 'Expression'),
+      'test_result' => array('type' => 'list<text>', 'label' => 'Result list of matches'),
+    ), array('string', 'expression', 'test_result'));
+    $action_set->action('data_regex', array('string:select' => 'string', 'expression:select' => 'expression'))
+      ->action('data_set', array('data:select' => 'test_result', 'value:select' => 'result'));
+    $action_set->integrityCheck();
+    // Test whole match.
+    list($dummy, $dummy, $result) = $action_set->execute('pgp is not php', '#p(?P<foo>.?)p#', array());
+    $expected = array('pgp', 'php');
+    $this->assertTrue($result == $expected, 'Searched regular expression whole matches.');
+    // Test regular expression named "result".
+    list($dummy, $dummy, $result) = $action_set->execute('pgp is not php', '#p(?P<result>.?)p#', array());
+    $expected = array('g', 'h');
+    $this->assertTrue($result == $expected, 'Searched regular expression named matches.');
   }
 
   /**
-- 
1.7.9.5

