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,118 @@ + 'checkbox', + '#title' => t('Enable event activation messages on forms'), + '#default_value' => isset($_SESSION['rules_forms_message']) ? $_SESSION['rules_forms_message'] : FALSE, + '#description' => t('If checked, there will be a message on each form containing a link to activate events for the form. Only visible for your currently logged in user account.'), + ); + $form['enable_form_element_ids'] = array( + '#type' => 'checkbox', + '#title' => t('Display form element IDs'), + '#default_value' => isset($_SESSION['rules_forms_element_ids']) ? $_SESSION['rules_forms_element_ids'] : FALSE, + '#description' => t('If checked, the identifier of every single form element will be displayed on event-activated forms. Only visible for your currently logged in user account.'), + ); + $form['settings_submit'] = array( + '#type' => 'submit', + '#value' => t('Save settings'), + '#submit' => array('rules_forms_settings_submit'), + ); + $form_events = variable_get('rules_forms_events', array()); + if (!empty($form_events)) { + $form['form_events'] = array( + '#type' => 'checkboxes', + '#title' => t('Forms where events are activated'), + '#options' => $form_events, + '#description' => t('Forms that currently invoke events. Select forms to deactivate events on them.'), + ); + $form['events_deactivate'] = array( + '#type' => 'submit', + '#value' => t('Deactivate events'), + '#submit' => array('rules_forms_events_deactivate_submit'), + ); + } + else { + drupal_set_message('Enable the event activation messages below and go to the form you would like to activate events on.', 'status', FALSE); + } + return $form; +} + +/** + * Submit handler to save settings. + */ +function rules_forms_settings_submit($form_id, $form_values) { + $_SESSION['rules_forms_message'] = (bool) $form_values['values']['enable_form_activation_message']; + $_SESSION['rules_forms_element_ids'] = (bool) $form_values['values']['enable_form_element_ids']; + drupal_set_message(t('The settings have been saved.')); +} + +/** + * Submit handler to deactivate form events. + */ +function rules_forms_events_deactivate_submit($form_id, $form_values) { + $deactivate_events = array_filter($form_values['values']['form_events']); + $form_events = variable_get('rules_forms_events', array()); + foreach ($deactivate_events as $key => $value) { + unset($form_events[$key]); + } + variable_set('rules_forms_events', $form_events); + drupal_set_message(t('The event 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,315 @@ + $label) { + $events[$form_id .'_form_built'] = array( + 'label' => t('@form is being built', array('@form' => $label)), + 'module' => 'Rules Forms', + 'arguments' => rules_forms_events_arguments(), + ); + $events[$form_id .'_form_submit'] = array( + 'label' => t('@form is submitted', array('@form' => $label)), + 'module' => 'Rules Forms', + 'arguments' => rules_forms_events_arguments(), + ); + $events[$form_id .'_form_validate'] = array( + 'label' => t('@form is being validated', array('@form' => $label)), + 'module' => 'Rules 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' => 'Rules 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('Form element ID'), + 'description' => t('The element that should not appear.') .' '. _rules_forms_element_description(), + ), + ), + 'module' => 'Rules 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.') .' '. _rules_forms_element_description(), + ), + 'weight' => array( + 'type' => 'number', + 'label' => t('Element weight'), + 'description' => t('Low numbers make the element bubble up, high numbers sink it down.'), + ), + ), + 'module' => 'Rules 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.') .' '. _rules_forms_element_description(), + ), + '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' => 'Rules Forms', + ), + 'rules_forms_action_set_error' => array( + 'label' => t('Set a form error'), + '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 marked.') .' '. _rules_forms_element_description(), + ), + 'message' => array( + 'type' => 'string', + 'label' => t('Message'), + 'description' => t('The message that should be displayed to the user.'), + ), + ), + 'module' => 'Rules Forms', + ), + ); +} + +function _rules_forms_element_description() { + return t('Examples on the "Create Story" form: "title" for the title field or "body_field[body]" for the body field.'); +} + +/** + * 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' => 'Rules Forms', + ), + 'form_state' => array( + 'label' => t('form_state'), + 'class' => 'rules_data_type', + 'savable' => FALSE, + 'identifiable' => FALSE, + 'uses_input_form' => FALSE, + 'module' => 'Rules 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, $element, $message) { + 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.') .' '. _rules_forms_element_description(), + ), + 'value' => array( + 'type' => 'string', + 'label' => t('Value(s)'), + 'description' => t('Value(s) assigned to the form element. If the form element allows multiple values, enter one value per line.'), + ), + ), + 'module' => 'Rules 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'])) { + // Multiple values come in as array + if (is_array($form_element['#value'])) { + $lines = explode("\r\n", $value); + return rules_forms_equal_array_values($lines, $form_element['#value']); + } + return $form_element['#value'] === $value; + } + if (isset($form_element['#default_value'])) { + if (is_array($form_element['#default_value'])) { + $lines = explode("\r\n", $value); + return rules_forms_equal_array_values($lines, $form_element['#default_value']); + } + return $form_element['#default_value'] === $value; + } + return FALSE; +} + +/** + * Returns TRUE if both arrays contain the same values, regardless of their keys + * and value ordering. + */ +function rules_forms_equal_array_values($array1, $array2) { + $diff1 = array_diff($array1, $array2); + $diff2 = array_diff($array2, $array1); + return empty($diff1) && empty($diff2); +} + +/** + * @} + */ \ 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,129 @@ +'. t('Settings and overview of form events.') .'
'; + } +} + +/** + * 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'; + if (!empty($_SESSION['rules_forms_element_ids'])) { + rules_forms_add_element_id($form); + } + } + // Display form ID message if enabled for this session. + if (!empty($_SESSION['rules_forms_message'])) { + $link = l($form_id, RULES_ADMIN_FORMS_PATH .'/'. $form_id .'/activate/'); + $msg = t('Activate events for '); + drupal_set_message($msg . $link, 'status', FALSE); + } +} + +/** + * 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') { + $element_id = '