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

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

diff --git a/modules/data.eval.inc b/modules/data.eval.inc
index 82a09f9..59b3464 100644
--- a/modules/data.eval.inc
+++ b/modules/data.eval.inc
@@ -90,6 +90,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, $string, $matches);
+  $result = isset($matches['result']) ? $matches['result'] : $matches[0];
+  return array('result' => $result);
+}
+
+
+/**
  * Info alter callback for the data_calc action.
  */
 function rules_action_data_calc_info_alter(&$element_info, RulesPlugin $element) {
diff --git a/modules/data.rules.inc b/modules/data.rules.inc
index 5751348..7981bc2 100644
--- a/modules/data.rules.inc
+++ b/modules/data.rules.inc
@@ -73,6 +73,38 @@ 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.  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('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')),
+      ),
+    ),
+  );
   $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 bec592d..e1fb709 100644
--- a/tests/rules.test
+++ b/tests/rules.test
@@ -1485,6 +1485,24 @@ class RulesIntegrationTestCase extends DrupalWebTestCase {
     list($dummy, $result) = $action_set->execute(7, array());
     $expected = explode(',', '0,1,2,3,4,5,6');
     $this->assertTrue($result == $expected, 'Integer converted to list.');
+
+    // 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

