Index: rules_forms/rules_forms.admin.inc
===================================================================
--- rules_forms/rules_forms.admin.inc	(revision 0)
+++ rules_forms/rules_forms.admin.inc	(revision 0)
@@ -0,0 +1,98 @@
+<?php
+// $Id$
+
+
+/**
+ * @file
+ * Implements forms events management screen.
+ */
+ 
+/**
+ * Defines the forms events settings form
+ */
+function rules_forms_admin_events(&$form_state) {
+  $form = array();
+  $form_events = variable_get('rules_forms_events', array());
+  $form['enable_form_id_message'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Enable form ID event activation message'),
+    '#default_value' => $_SESSION['rules_forms_message'],
+    '#description' => t('If checked, there will be a message on each form containing the form ID and a link to enable events for the form. Only visible for this session.'),
+  );
+  if (!empty($form_events)) {
+    $form['form_events'] = array(
+      '#type' => 'checkboxes',
+      '#title' => t('Form IDs that will provide events'),
+      '#default_value' => array_keys($form_events),
+      '#options' => $form_events,
+      '#description' => t('Currently activated form IDs that will fire events for usage with Rules.'),
+    );
+  }
+  else {
+    drupal_set_message('Enable the form activation messages below and go to the form you would like to activate for Rules.', 'status', FALSE);
+  }
+  $form['submit'] = array('#type' => 'submit', '#value' => t('Save'));
+  return $form;
+}
+
+/**
+ * Submit handler for updating rules forms settings.
+ */
+function rules_forms_admin_events_submit($form_id, $form_values) {
+  $form_events_changed = $form_values['values']['form_events'];
+  if (!empty($form_events_changed)) {
+    $form_events = variable_get('rules_forms_events', array());
+    // check events that have been unset
+    $form_events_remaining = array_filter($form_events_changed);
+    $form_events = array_intersect_key($form_events, $form_events_remaining);
+    variable_set('rules_forms_events', $form_events);
+  }
+  $_SESSION['rules_forms_message'] = (bool) $form_values['values']['enable_form_id_message'];
+  drupal_set_message(t('The settings have been saved.'));
+}
+
+/**
+ * Activation page for a form ID.
+ */
+function rules_forms_activate($form_id_activate) {
+  $form_events = variable_get('rules_forms_events', array());
+  if (isset($form_events[$form_id_activate])) {
+    return t('Events for %form_id have already been activated.', array('%form_id' => $form_id_activate));
+  }
+  return drupal_get_form('rules_forms_activate_form', $form_id_activate);
+}
+
+/**
+ * Confirmation form to activate events on a form.
+ */
+function rules_forms_activate_form(&$form_state, $form_id_activate) {
+  $default_form_label = drupal_ucfirst(str_replace('_', ' ', $form_id_activate));
+  $form = array(
+    'form_id_label' => array(
+        '#type' => 'textfield',
+        '#title' => t('Custom form label'),
+        '#default_value' => $default_form_label,
+        '#required' => TRUE,
+        '#description' => t('Enter a custom label to better recognize the form in the administration user interface.'),
+    ),
+  );
+  $form_state['form_id_activate'] = $form_id_activate;
+
+  $path = array();
+  $path['path'] = isset($_GET['destination']) ? $_GET['destination'] : RULES_ADMIN_FORMS_PATH;
+
+  $title = t('Are you sure you want to activate events for %form?', array('%form' => $form_id_activate));
+  $msg = t('Once the activation is confirmed, events on this form can be used to trigger rules.');
+  return confirm_form($form, $title, $path, $msg, t('Activate'), t('Cancel'));
+}
+
+/**
+ * Submit handler for activation of a form.
+ */
+function rules_forms_activate_form_submit($form, &$form_state) {
+  $form_events = variable_get('rules_forms_events', array());
+  $form_events[$form_state['form_id_activate']] = $form_state['values']['form_id_label'];
+  variable_set('rules_forms_events', $form_events);
+  drupal_set_message(t("%form has been activated.", array('%form' => $form_state['form_id_activate'])));
+  $form_state['redirect'] = RULES_ADMIN_FORMS_PATH;
+}
\ No newline at end of file
Index: rules_forms/rules_forms.rules.inc
===================================================================
--- rules_forms/rules_forms.rules.inc	(revision 0)
+++ rules_forms/rules_forms.rules.inc	(revision 0)
@@ -0,0 +1,293 @@
+<?php
+// $Id$
+
+
+/**
+ * @file
+ * Rules integration to provide form support
+ *
+ * @addtogroup rules
+ * @{
+ */
+
+/**
+ * Implementation of hook_rules_event_info().
+ */
+function rules_forms_rules_event_info() {
+  $form_events = variable_get('rules_forms_events', array());
+  $events = array();
+  foreach ($form_events as $form_id => $label) {
+    $events[$form_id .'_form_built'] = array(
+      'label' => t('@form is being built', array('@form' => $label)),
+      'module' => 'Forms',
+      'arguments' => rules_forms_events_arguments(),
+    );
+    $events[$form_id .'_form_submit'] = array(
+      'label' => t('@form is submitted', array('@form' => $label)),
+      'module' => 'Forms',
+      'arguments' => rules_forms_events_arguments(),
+    );
+    $events[$form_id .'_form_validate'] = array(
+      'label' => t('@form is being validated', array('@form' => $label)),
+      'module' => 'Forms',
+      'arguments' => rules_forms_events_arguments(),
+    );
+  }
+  return $events;
+}
+
+/**
+ * Returns some arguments suitable for hook form alter.
+ */
+function rules_forms_events_arguments() {
+  return array(
+    'form' => array('type' => 'form', 'label' => t('Form')),
+    'form_state' => array('type' => 'form_state', 'label' => t('Form state')),
+    'form_id' => array('type' => 'string', 'label' => t('Form ID')),
+  ) + rules_events_global_user_argument();
+}
+
+/**
+ * Implementation of hook_rules_action_info().
+ */
+function rules_forms_rules_action_info() {
+  return array(
+    'rules_forms_action_redirect' => array(
+      'label' => t('Set the redirect target of the form'),
+      'arguments' => array(
+        'form' => array('type' => 'form', 'label' => t('Form')),
+        'path' => array('type' => 'string', 'label' => t('Path')),
+        'query' => array('type' => 'string', 'label' => t('Query')),
+        'fragment' => array('type' => 'string', 'label' => t('Fragment')),
+      ),
+      'module' => 'Forms',
+      'help' => t('Enter a Drupal path, path alias, or external URL to redirect to. Enter (optional) queries after "?" and (optional) anchor after "#".'),
+    ),
+    'rules_forms_action_hide_element' => array(
+      'label' => t('Hide an element of the form'),
+      'arguments' => array(
+        'form' => array('type' => 'form', 'label' => t('Form')),
+        'hide' => array(
+          'type' => 'string',
+          'label' => t('Element ID to hide'),
+          'description' => t('The element that should not appear.'),
+        ),
+      ),
+      'module' => 'Forms',
+    ),
+    'rules_forms_action_adjust_weight' => array(
+      'label' => t('Adjust weight of an element in the form'),
+      'arguments' => array(
+        'form' => array('type' => 'form', 'label' => t('Form')),
+        'element' => array(
+          'type' => 'string',
+          'label' => t('Form element ID'),
+          'description' => t('The element that should be adjusted.'),
+        ),
+        'weight' => array(
+          'type' => 'number',
+          'label' => t('Element weight'),
+          'description' => t('Low numbers make the element bubble up, high numbers sink it down.'),
+        ),
+      ),
+      'module' => 'Forms',
+    ),
+    'rules_forms_action_prefix_suffix_html' => array(
+      'label' => t('Insert HTML prefix/suffix code'),
+      'arguments' => array(
+        'form' => array('type' => 'form', 'label' => t('Form')),
+        'element' => array(
+          'type' => 'string',
+          'label' => t('Form element ID'),
+          'description' => t('ID of the form element to be targeted.'),
+        ),
+        'prefix' => array(
+          'type' => 'string',
+          'label' => t('Prefixed HTML'),
+          'description' => t('HTML inserted before.'),
+        ),
+        'suffix' => array(
+          'type' => 'string',
+          'label' => t('Suffixed HTML'),
+          'description' => t('HTML inserted after.'),
+        ),
+      ),
+      'module' => 'Forms',
+    ),
+    'rules_forms_action_set_error' => array(
+      'label' => t('Set a form error'),
+      'arguments' => array(
+        'form' => array('type' => 'form', 'label' => t('Form')),
+        'message' => array(
+          'type' => 'string',
+          'label' => t('Message'),
+          'description' => t('The message that should be displayed to the user.'),
+        ),
+        'element' => array(
+          'type' => 'string',
+          'label' => t('Form element ID'),
+          'description' => t('The element that should be marked.'),
+        ),
+      ),
+      'module' => 'Forms',
+    ),
+  );
+}
+
+/**
+ * Implementation of hook_rules_data_type_info().
+ */
+function rules_forms_rules_data_type_info() {
+  return array(
+    'form' => array(
+      'label' => t('form'),
+      'class' => 'rules_data_type',
+      'savable' => FALSE,
+      'identifiable' => FALSE,
+      'uses_input_form' => FALSE,
+      'module' => 'Forms',
+    ),
+    'form_state' => array(
+      'label' => t('form_state'),
+      'class' => 'rules_data_type',
+      'savable' => FALSE,
+      'identifiable' => FALSE,
+      'uses_input_form' => FALSE,
+      'module' => 'Forms',
+    ),
+  );
+}
+
+/**
+ * Action implementation: Set the redirect target.
+ */
+function rules_forms_action_redirect(&$form, $path, $query, $fragment) {
+  $form['#redirect'] = array($path, $query, $fragment);
+}
+
+/**
+ * Action implementation: Hide a form element.
+ */
+function rules_forms_action_hide_element(&$form, $hide) {
+  $form_element = &_rules_forms_get_element($form, $hide);
+  $form_element['#access'] = FALSE;
+}
+
+/**
+ * Action implementation: Adjust weight of a form element.
+ */
+function rules_forms_action_adjust_weight(&$form, $element, $weight) {
+  // CCK overrides weight settings in #content_extra_fields
+  if (isset($form['#content_extra_fields'][$element]['weight'])) {
+    $form['#content_extra_fields'][$element]['weight'] = $weight;
+  }
+  else {
+    $form_element = &_rules_forms_get_element($form, $element);
+    $form_element['#weight'] = $weight;
+  }
+}
+
+/**
+ * Action implementation: Insert prefix/suffix HTML code.
+ */
+function rules_forms_action_prefix_suffix_html(&$form, $element, $prefix, $suffix) {
+  if (empty($element)) {
+    if (!empty($prefix)) {
+      $form['#prefix'] = $prefix;
+    }
+    if (!empty($suffix)) {
+      $form['#suffix'] = $suffix;
+    }
+  }
+  else {
+    $form_element = &_rules_forms_get_element($form, $element);
+    if (!empty($prefix)) {
+      $form_element['#prefix'] = $prefix;
+    }
+    if (!empty($suffix)) {
+      $form_element['#suffix'] = $suffix;
+    }
+  }
+}
+
+/**
+ * Action implementation: set form error.
+ */
+function rules_forms_action_set_error(&$form, $message, $element) {
+  // get element in form, #parent, implode()
+  if (substr($element, strlen($element)-1) === ']') {
+    $form_element = _rules_forms_get_element($form, $element);
+    if (isset($form_element['#parents'])) {
+      $element = implode('][', $form_element['#parents']);
+    }
+    else {
+      // remove trailing ']'
+      $element = substr($element, 0, strlen($element)-1);
+      // insert ']' before the first '['
+      $first_part = substr($element, 0, strpos($element, '['));
+      $second_part = substr($element, strpos($element, '['));
+      $element = $first_part .']'. $second_part;
+    }
+  }
+  form_set_error($element, $message);
+}
+
+/**
+ * Helper function to extract a reference to a form element by a given name.
+ */
+function &_rules_forms_get_element(&$form, $name) {
+  $names = explode('[', $name);
+  $element = &$form;
+  foreach ($names as $name) {
+    if (substr($name, strlen($name)-1) === ']') {
+      // remove trailing ']'
+      $name = substr($name, 0, strlen($name)-1);
+    }
+    $element = &$element[$name];
+  }
+  return $element;
+}
+
+/**
+ * Implementation of hook_rules_condition_info().
+ */
+function rules_forms_rules_condition_info() {
+  return array(
+    'rules_forms_condition_element_value' => array(
+      'label' => t('Form element has value'),
+      'arguments' => array(
+        'form' => array('type' => 'form', 'label' => t('Form')),
+        'form_state' => array('type' => 'form_state', 'label' => t('Form state')),
+        'element' => array(
+          'type' => 'string',
+          'label' => t('Form element ID'),
+          'description' => t('ID of the form element to be targeted.'),
+        ),
+        'value' => array(
+          'type' => 'string',
+          'label' => t('Value'),
+          'description' => t('Value assigned to the form element'),
+        ),
+      ),
+      'module' => 'Forms',
+    ),
+  );
+}
+
+/**
+ * Condition implementation: Check a form element value.
+ */
+function rules_forms_condition_element_value($form, $form_state, $element, $value) {
+  $form_element = _rules_forms_get_element($form, $element);
+  if (isset($form_element['#value']) && $form_element['#value'] === $value) {
+    return TRUE;
+  }
+  if (isset($form_element['#default_value']) && $form_element['#default_value'] === $value) {
+    return TRUE;
+  }
+  return FALSE;
+}
+
+/**
+ * @}
+ */
\ No newline at end of file
Index: rules_forms/rules_forms.module
===================================================================
--- rules_forms/rules_forms.module	(revision 0)
+++ rules_forms/rules_forms.module	(revision 0)
@@ -0,0 +1,128 @@
+<?php
+// $Id$
+
+
+/**
+ * @file
+ * Rules forms module.
+ */
+
+// Defines paths of the admin interface
+define('RULES_ADMIN_FORMS_PATH', RULES_ADMIN_PATH .'/forms');
+
+
+/**
+ * Implementation of hook_help().
+ */
+function rules_forms_help($path, $arg) {
+  if ($path === RULES_ADMIN_FORMS_PATH) {
+    return '<p>'. t('Overview of forms on the site that are enabled to trigger form events.') .'</p>';
+  }
+}
+
+/**
+ * Implementation of hook_menu().
+ */
+function rules_forms_menu() {
+  $items = array();
+  $items[RULES_ADMIN_FORMS_PATH] = array(
+    'title' => 'Form events',
+    'description' => 'Configure Rules forms events.',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('rules_forms_admin_events'),
+    'access arguments' => array('administer rules'),
+    'type' => MENU_NORMAL_ITEM,
+    'weight' => 6,
+    'file' => 'rules_forms.admin.inc',
+  );
+  $items[RULES_ADMIN_FORMS_PATH .'/%/activate'] = array(
+    'title' => 'Activate events for a form',
+    'type' => MENU_CALLBACK,
+    'page callback' => 'rules_forms_activate',
+    'page arguments' => array(3),
+    'access arguments' => array('administer rules'),
+    'file' => 'rules_forms.admin.inc',
+  );
+  return $items;
+}
+
+/**
+ * Implementation of hook_form_alter().
+ */
+function rules_forms_form_alter(&$form, &$form_state, $form_id) {
+  $form_events = variable_get('rules_forms_events', array());
+  // Invoke event if form is enabled
+  if (isset($form_events[$form_id])) {
+    rules_forms_invoke_event('form_built', $form, $form_state, $form_id);
+    $form['#after_build'][] = 'rules_forms_after_build';
+  }
+  // Display form ID message if enabled for this session.
+  if ($_SESSION['rules_forms_message']) {
+    $msg = t('Form ID: %id, ', array('%id' => $form_id));
+    $link = l(t('activate events'), RULES_ADMIN_FORMS_PATH .'/'. $form_id .'/activate/');
+    drupal_set_message($msg . $link, 'status', FALSE);
+    if (isset($form_events[$form_id])) {
+      //drupal_add_css(drupal_get_path('module', 'rules_forms') .'/rules_forms.css');
+      rules_forms_add_element_id($form);
+    }
+  }
+}
+
+/**
+ * Submit handler to invoke "form submitted" events
+ */
+function rules_forms_event_submit(&$form, &$form_state) {
+  rules_forms_invoke_event('form_submit', $form, $form_state);
+}
+
+/**
+ * Validation handler to invoke "form validate" events
+ */
+function rules_forms_event_validate(&$form, &$form_state) {
+  rules_forms_invoke_event('form_validate', $form, $form_state);
+}
+
+/**
+ * Invoke rules event of a certain type.
+ */
+function rules_forms_invoke_event($event_type, &$form, &$form_state, $form_id = NULL) {
+  if (empty($form_id)) {
+    $form_id = $form['form_id']['#value'];
+  }
+  $action_args = array(
+    'form' => &$form,
+    'form_state' => &$form_state,
+    'form_id' => $form_id,
+  );
+  rules_invoke_event($form_id .'_'. $event_type, $action_args);
+}
+
+/**
+ * Add element IDs as suffix code to all form elements.
+ */
+function rules_forms_add_element_id(&$form, $parent = '') {
+  $bracket = ($parent === '') ? '' : ']';
+  foreach (element_children($form) as $key) {
+    if (!isset($form[$key]['#type']) || $form[$key]['#type'] === 'hidden' || $form[$key]['#type'] === 'token') {
+      $form[$key]['#suffix'] .= '<div class="rules_forms_element_id">'. t('Hidden Element ID: %elem', array('%elem' => $parent . $key . $bracket)) .'</div>';
+    }
+    else {
+      $form[$key]['#suffix'] .= '<div class="rules_forms_element_id">'. t('Element ID: %elem', array('%elem' => $parent . $key . $bracket)) .'</div>';
+    }
+    rules_forms_add_element_id($form[$key], $parent . $key . $bracket .'[');
+  }
+}
+
+/**
+ * Add submit and validation callbacks to form, buttons, etc. to invoke
+ * corresponding events.
+ */
+function rules_forms_after_build($form, &$form_state) {
+  drupal_add_css(drupal_get_path('module', 'rules_forms') .'/rules_forms.css');
+  if (!$form_state['submitted']) {
+    return $form;
+  }
+  $form_state['submit_handlers'][] = 'rules_forms_event_submit';
+  $form_state['validate_handlers'][] = 'rules_forms_event_validate';
+  return $form;
+}
\ No newline at end of file
Index: rules_forms/rules_forms.rules_forms.inc
===================================================================
--- rules_forms/rules_forms.rules_forms.inc	(revision 0)
+++ rules_forms/rules_forms.rules_forms.inc	(revision 0)
@@ -0,0 +1,134 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Contains forms for rules forms actions.
+ */
+
+/**
+ * Action redirect configuration form.
+ */
+function rules_forms_action_redirect_form($settings, &$form) {
+  $settings += array('path' => '', 'query' => '', 'fragment' => '');
+
+  $form['settings']['path'] = array(
+    '#type' => 'textfield',
+    '#size' => 30,
+    '#prefix' => '<br /><div class="container-inline">',
+    '#title' => t('To'),
+    '#suffix' => '?',
+    '#default_value' => $settings['path'],
+  );
+  $form['settings']['query'] = array(
+    '#type' => 'textfield',
+    '#size' => 12,
+    '#default_value' => $settings['query'],
+    '#suffix' => '#',
+  );
+  $form['settings']['fragment'] = array(
+    '#type' => 'textfield',
+    '#size' => 12,
+    '#default_value' => $settings['fragment'],
+    '#suffix' => '</div>',
+  );
+}
+
+/**
+ * Action adjust weight configuration form.
+ */
+function rules_forms_action_adjust_weight_form($settings, &$form) {
+  $form['settings']['weight']['#type'] = 'weight';
+  $form['settings']['weight']['#delta'] = 50;
+  if (isset($settings['weight'])) {
+    $form['settings']['weight']['#default_value'] = $settings['weight'];
+  }
+  else {
+    $form['settings']['weight']['#default_value'] = 0;
+  }
+}
+
+/**
+ * Action prefix/suffix code configuration form.
+ */
+function rules_forms_action_prefix_suffix_html_form($settings, &$form) {
+  $form['settings']['element']['#required'] = FALSE;
+  $form['settings']['element']['#description'] = t('ID of the form element to be targeted. Leave empty to apply prefix/suffix code to the whole form.');
+  $form['settings']['prefix']['#type'] = 'textarea';
+  $form['settings']['prefix']['#required'] = FALSE;
+  $form['settings']['suffix']['#type'] = 'textarea';
+  $form['settings']['suffix']['#required'] = FALSE;
+}
+
+/**
+ * Action set error configuration form.
+ */
+function rules_forms_action_set_error_form($settings, &$form) {
+  $form['settings']['element']['#required'] = FALSE;
+}
+
+/**
+ * Validation of the prefix/suffix action configuration form.
+ */
+function rules_forms_action_prefix_suffix_html_validate($form, $form_state) {
+  if (empty($form_state['values']['settings']['prefix']) && empty($form_state['values']['settings']['suffix'])) {
+    form_set_error('settings][prefix', t('You have to specify at least the prefix or suffix field.'));
+  }
+}
+
+/**
+ * Label callback for adjusting weights action.
+ */
+function rules_forms_action_adjust_weight_label($settings, $argument_labels) {
+  return t("Adjust weight of form element '@element' to @weight", array('@element' => $settings['element'], '@weight' => $settings['weight']));
+}
+
+/**
+ * Label callback for hiding form elements action.
+ */
+function rules_forms_action_hide_element_label($settings, $argument_labels) {
+  return t("Hide form element '@element'", array('@element' => $settings['hide']));
+}
+
+/**
+ * Label callback for redirect action.
+ */
+function rules_forms_action_redirect_label($settings, $argument_labels) {
+  $redirect = $settings['path'];
+  if (!empty($settings['query'])) {
+    $redirect .= '?'. $settings['query'];
+  }
+  if (!empty($settings['fragment'])) {
+    $redirect .= '#'. $settings['fragment'];
+  }
+  return t("Set form redirect target to '@redirect'", array('@redirect' => $redirect));
+}
+
+/**
+ * Label callback for prefix/suffix action.
+ */
+function rules_forms_action_prefix_suffix_html_label($settings, $argument_labels) {
+  if (empty($settings['element'])) {
+    return t('Insert HTML prefix/suffix code on form');
+  }
+  else {
+    return t("Insert HTML prefix/suffix code on '@element'", array('@element' => $settings['element']));
+  }
+}
+
+/**
+ * Label callback for set error action.
+ */
+function rules_forms_action_set_error_label($settings, $argument_labels) {
+  if (empty($settings['element'])) {
+    return t('Set a form error');
+  }
+  return t("Set form error on element '@element'", array('@element' => $settings['element']));
+}
+
+/**
+ * Label callback for element value condition.
+ */
+function rules_forms_condition_element_value_label($settings, $argument_labels) {
+  return t("Form element '@element' value check", array('@element' => $settings['element']));
+}
\ No newline at end of file
Index: rules_forms/rules_forms.css
===================================================================
--- rules_forms/rules_forms.css	(revision 0)
+++ rules_forms/rules_forms.css	(revision 0)
@@ -0,0 +1,5 @@
+/* $Id$ */
+
+div.rules_forms_element_id {
+  font-size: 80%;
+}
Index: rules_forms/rules_forms.info
===================================================================
--- rules_forms/rules_forms.info	(revision 0)
+++ rules_forms/rules_forms.info	(revision 0)
@@ -0,0 +1,6 @@
+; $Id$
+name = Rules Forms support
+description = Provides events, conditions and actions for rule-based form customization.
+dependencies[] = rules
+package = Rules
+core = 6.x
\ No newline at end of file
