diff --git a/includes/rules_forms.admin.inc b/includes/rules_forms.admin.inc old mode 100755 new mode 100644 index a98255b..c4684ed --- a/includes/rules_forms.admin.inc +++ b/includes/rules_forms.admin.inc @@ -19,8 +19,7 @@ function rules_forms_admin_events($form, &$form_state) { '#type' => '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.'), + '#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['general_settings']['settings_submit'] = array( '#type' => 'submit', @@ -53,8 +52,7 @@ function rules_forms_admin_events($form, &$form_state) { ); } else { - drupal_set_message(t('To begin create form rules, enable the event activation messages below and navigate '. - 'to the form you would like to activate events on.'), 'status', FALSE); + drupal_set_message(t('To begin create form rules, enable the event activation messages below and navigate to the form you would like to activate events on.'), 'status', FALSE); } return $form; } @@ -82,14 +80,14 @@ function rules_forms_events_deactivate_submit($form_id, $form_state) { /** * Activation page for a form ID. * - * @param $form_id_activate + * @param string $form_id_activate * The form ID of the form to be activated. - * @param $form_page - * The encoded URI of the page on which the form was activated. This is used for - * redirecting the user back to that page once activation is completed. + * @param string $form_page + * The encoded URI of the page on which the form was activated. This is used + * to redirect the user back to that page once activation is completed. */ function rules_forms_activate($form_id_activate, $form_page) { - if ($form_info = rules_forms_get_form_info($form_id_activate)) { + if (rules_forms_get_form_info($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_confirm_form', $form_id_activate, $form_page); @@ -129,7 +127,8 @@ function rules_forms_activate_confirm_form_submit($form, &$form_state) { 'label' => $form_state['values']['form_id_label'], ); - // Save the form information but prevent cache rebuild until the form is visited. + // Save the form information but prevent cache from being rebuilt until the + // form is visited. rules_forms_activate_form($form_info); rules_forms_clear_cache(); drupal_set_message(t("%form has been activated.", array('%form' => $form_state['form_id_activate']))); diff --git a/includes/rules_forms.eval.inc b/includes/rules_forms.eval.inc old mode 100755 new mode 100644 index 2bbf5e6..dabfbf6 --- a/includes/rules_forms.eval.inc +++ b/includes/rules_forms.eval.inc @@ -7,6 +7,7 @@ /** * Info alter callback for the element has value condition. + * * Sets the value field according to the type of value the element uses. */ function rules_forms_element_value_info_alter(&$element_info, $element) { @@ -56,31 +57,31 @@ function rules_forms_condition_element_value($wrapper, $value, $regex, $settings * Condition: Form element attribute has value. */ function rules_forms_condition_attribute_value($wrapper, $value, $regex, $settings, $state, $element) { - if ($wrapper instanceof RulesFormsAttributeWrapper) { - $attribute_value = $wrapper->value(); - // Perform the comparison with a regular expression if necessary. - if ($wrapper->type() == 'text' && $regex) { - // Allow multiple regular expressions to be run, one on each line. - // Return FALSE immediately if an expression fails. - $lines = explode("\r\n", $value); - foreach ($lines as $line) { - $result = preg_match($value, $attribute_value) == 1; - if ($result === FALSE) { - return FALSE; - } - } - return TRUE; - } - - // Multiple values come in as array. - if (is_array($attribute_value)) { - $lines = explode("\r\n", $value); - return rules_forms_equal_array_values($lines, $attribute_value); - } - return $attribute_value === $value; - } - else { - return $wrapper === $value; + if ($wrapper instanceof RulesFormsAttributeWrapper) { + $attribute_value = $wrapper->value(); + // Perform the comparison with a regular expression if necessary. + if ($wrapper->type() == 'text' && $regex) { + // Allow multiple regular expressions to be run, one on each line. + // Return FALSE immediately if an expression fails. + $lines = explode("\r\n", $value); + foreach ($lines as $line) { + $result = preg_match($value, $attribute_value) == 1; + if ($result === FALSE) { + return FALSE; + } + } + return TRUE; + } + + // Multiple values come in as array. + if (is_array($attribute_value)) { + $lines = explode("\r\n", $value); + return rules_forms_equal_array_values($lines, $attribute_value); + } + return $attribute_value === $value; + } + else { + return $wrapper === $value; } } @@ -97,7 +98,8 @@ function rules_forms_condition_element_changed(RulesFormsElementWrapper $form_el $element_name = substr($settings['data:select'], strpos($settings['data:select'], ':') + 1); $build_values = $_SESSION['rules_forms_form_values'][$form_id]; - // Ensure that form values are set. This will prevent the condition from being evaluated during build. + // Ensure that form values are set. This will prevent the condition from + // being evaluated during build. if (isset($build_values[$element_name]) && isset($form_state['values']) && isset($form_state['values'][$element_name])) { return $build_values[$element_name] !== $form_state['values'][$element_name]; } @@ -118,7 +120,7 @@ function rules_forms_condition_element_changed(RulesFormsElementWrapper $form_el * @return bool * Indicates whether the indicated button was clicked. */ -function rules_forms_condition_button_clicked($form_state, EntityStructureWrapper $form_element, $settings, $state, $element) { +function rules_forms_condition_button_clicked(RulesFormsFormStateWrapper $form_state, EntityStructureWrapper $form_element, $settings, $state, $element) { $form_state = $form_state->value(); $form_element = $form_element->value(); if (isset($form_state['triggering_element'])) { @@ -134,8 +136,7 @@ function rules_forms_condition_button_clicked($form_state, EntityStructureWrappe } /** - * Returns TRUE if both arrays contain the same values, regardless - * of their keys and value ordering. + * Compare two arrays values regardless of their elements order. * * @param array $array1 * An array to compare against $array2. @@ -143,7 +144,7 @@ function rules_forms_condition_button_clicked($form_state, EntityStructureWrappe * An array to compare against $array1. * * @return bool - * Indicates whether the input arrays are equal. + * TRUE if both arrays are equal regardless of their elements order. */ function rules_forms_equal_array_values($array1, $array2) { $diff1 = array_diff($array1, $array2); @@ -166,7 +167,7 @@ function rules_forms_action_attribute_set(EntityMetadataWrapper $wrapper, $value $wrapper->set($value); } } - catch (EntityMetadataWrapperException $e) { + catch (EntityMetadataWrapperException $e) { throw new RulesEvaluationException('Unable to modify data "@selector": ' . $e->getMessage(), array('@selector' => $settings['data:select'])); } } @@ -174,14 +175,15 @@ function rules_forms_action_attribute_set(EntityMetadataWrapper $wrapper, $value return array('data' => $value); } } - -/** - * Info alter callback for the attribute_set action. - * Load the Rules callback. - */ -function rules_forms_action_attribute_set_info_alter(&$element_info, $element) { - module_load_include('inc', 'rules', 'modules/data.eval'); - rules_action_data_set_info_alter($element_info, $element); + +/** + * Info alter callback for the attribute_set action. + * + * Load the Rules callback. + */ +function rules_forms_action_attribute_set_info_alter(&$element_info, $element) { + module_load_include('inc', 'rules', 'modules/data.eval'); + rules_action_data_set_info_alter($element_info, $element); } /** @@ -197,7 +199,7 @@ function rules_forms_action_attribute_set_info_alter(&$element_info, $element) { * @param string $fragment * A fragement string for use in drupal_goto(). */ -function rules_forms_action_redirect($form_state, $path, $query, $fragment) { +function rules_forms_action_redirect(RulesFormsFormStateWrapper $form_state, $path, $query, $fragment) { $form_state = $form_state->value(); // We manually check the form to see if redirect is okay. // Setting $form_state['redirect'] has proven to be unreliable. @@ -216,7 +218,7 @@ function rules_forms_action_redirect($form_state, $path, $query, $fragment) { /** * Action: Set form error. * - * @param EntityStructureWrapper + * @param EntityMetadataWrapper $wrapper * The wrapped form element on which to set the error, if any. * @param string $message * The error message to set on the form element. @@ -233,11 +235,12 @@ function rules_forms_action_set_error(EntityMetadataWrapper $wrapper, $message, } /** - * Action: Set multiple value options of a form element. + * Set multiple value options of a form element. + * * Note: For multiple option values each key value pair is on its own line * and formatted key|value. * - * @param RulesFormsAttributeWrapper $wrapper + * @param EntityMetadataWrapper $wrapper * The wrapped form element attribute. * @param string $value * A value to assign to the element's #options attribute. This value diff --git a/includes/rules_forms.info.inc b/includes/rules_forms.info.inc index 87d9c7e..ea7e33c 100644 --- a/includes/rules_forms.info.inc +++ b/includes/rules_forms.info.inc @@ -1,421 +1,506 @@ - t('Button'), - 'properties' => rules_forms_element_properties('button'), - 'element info' => array( - 'data type' => 'text', - 'keys' => array('value' => '#value'), - 'empty' => '', - ), - ); - $info['checkbox'] = array( - 'label' => t('Checkbox'), - 'properties' => rules_forms_element_properties('checkbox'), - 'element info' => array( - 'data type' => 'boolean', - 'keys' => array('value' => '#value', 'default_value' => '#default_value'), - 'empty' => FALSE, - ), - ); - $info['checkboxes'] = array( - 'label' => t('Checkboxes'), - 'properties' => rules_forms_element_properties('checkboxes'), - 'element info' => array( - 'data type' => 'struct', - 'keys' => array('value' => '#value', 'default_value' => '#default_value'), - 'empty' => array(), - ), - ); - $info['container'] = array( - 'label' => t('Container'), - 'properties' => rules_forms_element_properties('container'), - // The 'data type' FALSE indicates that this element is not settable. - 'element info' => array('data type' => FALSE), - ); - $info['fieldset'] = array( - 'label' => t('Fieldset'), - 'properties' => rules_forms_element_properties('fieldset'), - // The 'data type' FALSE indicates that this element is not settable. - 'element info' => array('data type' => FALSE), - ); - $info['hidden'] = array( - 'label' => t('Hidden'), - 'properties' => rules_forms_element_properties('hidden'), - 'element info' => array( - 'data type' => '*', - 'keys' => array('value' => '#value'), - 'empty' => NULL, - ), - ); - $info['item'] = array( - 'label' => t('Item'), - 'properties' => rules_forms_element_properties('item'), - 'element info' => array( - 'data type' => 'text', - 'keys' => array('value' => '#markup'), - 'empty' => '', - ), - ); - $info['markup'] = array( - 'label' => t('Markup'), - 'properties' => rules_forms_element_properties('markup'), - 'element info' => array( - 'data type' => 'text', - 'keys' => array('value' => '#markup'), - 'empty' => '', - ), - ); - $info['password'] = array( - 'label' => t('Password'), - 'properties' => rules_forms_element_properties('password'), - 'element info' => array( - 'data type' => 'text', - 'keys' => array('value' => '#value'), - 'empty' => NULL, - ), - ); - $info['radio'] = array( - 'label' => t('Radio'), - 'properties' => rules_forms_element_properties('radio'), - 'element info' => array( - 'data type' => 'text', - 'keys' => array('value' => '#value', 'default_value' => '#default_value'), - 'empty' => NULL, - ), - ); - $info['radios'] = array( - 'label' => t('Radios'), - 'properties' => rules_forms_element_properties('radios'), - 'element info' => array( - 'data type' => 'text', - 'keys' => array('value' => '#value', 'default_value' => '#default_value'), - 'empty' => '', - ), - ); - $info['select'] = array( - 'label' => t('Select list'), - 'properties' => rules_forms_element_properties('select'), - 'element info' => array( - 'data type' => 'text|struct', - 'keys' => array('value' => '#value', 'default_value' => '#default_value'), - 'empty' => '', - ), - ); - $info['submit'] = array( - 'label' => t('Submit'), - 'properties' => rules_forms_element_properties('submit'), - 'element info' => array( - 'data type' => 'text', - 'keys' => array('value' => '#value'), - 'empty' => '', - ), - ); - $info['tableselect'] = array( - 'label' => t('Table select list'), - 'properties' => rules_forms_element_properties('tableselect'), - 'element info' => array( - 'data type' => 'struct', - 'keys' => array('value' => '#value', 'default_value' => '#default_value'), - 'empty' => array(), - ), - ); - $info['text_format'] = array( - 'label' => t('Text format'), - 'properties' => rules_forms_element_properties('text_format'), - 'element info' => array( - 'data type' => 'text', - 'keys' => array('value' => '#value', 'default_value' => '#default_value'), - 'empty' => '', - ), - ); - $info['textarea'] = array( - 'label' => t('Text area'), - 'properties' => rules_forms_element_properties('textarea'), - 'element info' => array( - 'data type' => 'text', - 'keys' => array('value' => '#value', 'default_value' => '#default_value'), - 'empty' => '', - ), - ); - $info['textfield'] = array( - 'label' => t('Text field'), - 'properties' => rules_forms_element_properties('textfield'), - 'element info' => array( - 'data type' => 'text', - 'keys' => array('value' => '#value', 'default_value' => '#default_value'), - 'empty' => '', - ), - ); - $info['weight'] = array( - 'label' => t('Weight'), - 'properties' => rules_forms_element_properties('weight'), - 'element info' => array( - 'data type' => 'integer', - 'keys' => array('value' => '#value', 'default_value' => '#default_value'), - 'empty' => 0, - ), - ); - $info['value'] = array( - 'label' => t('Value'), - 'properties' => rules_forms_element_properties('value'), - 'element info' => array( - 'data type' => '*', - 'keys' => array('value' => '#value'), - 'empty' => '', - ), - ); - return $info; -} - -/** - * Returns an array of attribute property info for a specific form element type. - * - * @param string $element_type - * The form element type. This is an element type defined in - * hook_rules_forms_element_info(). - */ -function rules_forms_element_properties($element_type) { - $attribute_info = _rules_forms_attribute_info(); - $attributes = array(); - foreach ($attribute_info as $attribute => $info) { - if ($info['attribute info']['elements'] == 'all' || in_array($element_type, $info['attribute info']['elements'])) { - $attributes[$attribute] = _rules_forms_build_element_property($info); - } - } - return $attributes; -} - -/** - * Returns an array of element properties based on existing attributes. - */ -function rules_forms_filter_element_properties($element) { - $attribute_info = _rules_forms_attribute_info(); - $attributes = array(); - foreach (element_properties($element) as $attribute => $info) { - if (isset($attribute_info[$attribute])) { - $attributes[$attribute] = _rules_forms_build_element_property($info); - } - } - return $attributes; -} - -/** - * Builds the property info of an individual property from an array of info. - */ -function _rules_forms_build_element_property(array $info) { - $info += array( - 'getter callback' => 'entity_property_verbatim_get', - 'computed' => TRUE, - 'attribute info' => array(), - ); - $info['attribute info'] += array('read only' => FALSE); - if (empty($info['attribute info']['read only'])) { - $info += array('setter callback' => 'entity_property_verbatim_set'); - } - // Unset the 'elements' and 'read only' portions as those are not used in wrappers. - unset($info['attribute info']['elements'], $info['attribute info']['read only']); - return $info; -} - -/** - * Returns an array of attribute property info and data indicating - * which element types each attribute is supported on. - */ -function _rules_forms_attribute_info() { - return array( - '#access' => array( - 'type' => 'boolean', - 'label' => t('Visible'), - 'description' => t('Whether the element is accessible or not; when FALSE, the element is not rendered and the user submitted value is not taken into consideration.'), - 'attribute info' => array('elements' => 'all'), - ), - '#collapsed' => array( - 'type' => 'boolean', - 'label' => t('Collapsed'), - 'description' => t('Indicates whether or not the fieldset is collapsed by default.'), - 'attribute info' => array('elements' => array('fieldset')), - ), - '#collapsible' => array( - 'type' => 'boolean', - 'label' => t('Collapsible'), - 'description' => t('Indicates whether or not the fieldset can be collapsed with JavaScript.'), - 'attribute info' => array('elements' => array('fieldset')), - ), - '#cols' => array( - 'type' => 'int', - 'label' => t('Columns'), - 'description' => t('How many columns wide the textarea should be.'), - 'attribute info' => array('elements' => array('text_format', 'textarea')), - ), - '#default_value' => array( - 'type' => 'text', - 'label' => t('Default value'), - 'description' => t('The value of the form element that will be displayed or selected initially if the form has not been submitted yet.'), - 'attribute info' => array( - 'elements' => array('checkbox', 'checkboxes', 'hidden', 'radio', 'radios', 'select', 'tableselect', 'text_format', 'textarea', 'textfield', 'weight'), - ), - ), - '#description' => array( - 'type' => 'text', - 'label' => t('Description'), - 'description' => t('The description of the form element.'), - 'attribute info' => array( - 'elements' => array('checkbox', 'checkboxes', 'hidden', 'item', 'password' 'radio', 'radios', 'select', 'tableselect', 'text_format', 'textarea', 'textfield', 'weight'), - ), - ), - '#disabled' => array( - 'type' => 'boolean', - 'label' => t('Disabled'), - 'description' => t('Disables (greys out) a form input element.'), - 'attribute info' => array( - 'elements' => array('button', 'checkbox', 'checkboxes', 'password', 'radio', 'radios', 'select', 'submit', 'text_format', 'textarea', 'textfield', 'weight', 'text_format'), - ), - ), - '#field_prefix' => array( - 'type' => 'text', - 'label' => t('Field prefix text or HTML'), - 'sanitize' => 'check_markup', - 'description' => t('Text or code that is placed directly in front of the textfield.'), - 'attribute info' => array('elements' => array('checkbox', 'radio', 'select', 'textarea', 'textfield')), - ), - '#field_suffix' => array( - 'type' => 'text', - 'label' => t('Field suffix text or HTML'), - 'sanitize' => 'check_markup', - 'description' => t('Text or code that is placed directly after the textfield.'), - 'attribute info' => array('elements' => array('checkbox', 'radio', 'select', 'textarea', 'textfield')), - ), - '#markup' => array( - 'type' => 'text', - 'label' => t('HTML'), - 'sanitize' => 'check_markup', - 'description' => t('Used to set HTML that will be output on the form.'), - 'attribute info' => array('elements' => array('item', 'markup')), - ), - '#multiple' => array( - 'type' => 'boolean', - 'label' => t('Allow multiple'), - 'description' => t('Indicates whether the user may select more than one item.'), - 'attribute info' => array( - 'elements' => array('select'), - 'read only' => TRUE, - ), - ), - '#name' => array( - 'type' => 'text', - 'label' => t('Name'), - 'description' => t('The form element name. This can be used as an identifer.'), - 'attribute info' => array('elements' => array('button', 'submit')), - ), - '#options' => array( - 'type' => 'text', - 'label' => t('Options'), - 'description' => t('Selectable options for a form element that allows multiple choices.'), - 'attribute info' => array( - 'elements' => array('select', 'checkboxes', 'radios', 'tableselect'), - 'validate callback' => 'rules_forms_options_set_validate', - 'setter callback' => 'rules_forms_options_set', - ), - ), - '#prefix' => array( - 'type' => 'text', - 'label' => t('Prefix text or HTML'), - 'description' => t('Text or markup to include before the form element.'), - 'attribute info' => array('elements' => 'all'), - ), - '#required' => array( - 'type' => 'boolean', - 'label' => t('Required'), - 'description' => t('Indicates whether or not the element is required. This automatically validates for empty fields, and flags inputs as required.'), - 'attribute info' => array( - 'elements' => array('checkbox', 'checkboxes', 'password', 'radio', 'radios', 'select', 'textarea', 'text_format', 'textfield', 'weight'), - ), - ), - '#resizable' => array( - 'type' => 'boolean', - 'label' => t('Resizable'), - 'description' => t('Indicates whether users should be allowed to resize the text area.'), - 'attribute info' => array('elements' => array('text_format', 'textarea')), - ), - '#rows' => array( - 'type' => 'int', - 'label' => t('Rows'), - 'description' => t('How many rows high the textarea should be.'), - 'attribute info' => array('elements' => array('text_format', 'textarea')), - ), - '#size' => array( - 'type' => 'int', - 'label' => t('Size'), - 'description' => t('Width of the textfield (in characters) or size of multiselect box (in lines).'), - 'attribute info' => array('elements' => array('select', 'password', 'textfield')), - ), - '#suffix' => array( - 'type' => 'text', - 'label' => t('Suffix text or HTML'), - 'description' => t('Text or markup to include after the form element.'), - 'attribute info' => array('elements' => 'all'), - ), - '#title' => array( - 'type' => 'text', - 'label' => t('Title'), - 'description' => t('The title of the form element.'), - 'attribute info' => array( - 'elements' => array('button', 'checkbox', 'checkboxes', 'password', 'radio', 'radios', 'select', 'submit', 'text_format', 'textarea', 'textfield', 'weight', 'text_format', 'item'), - ), - ), - '#tree' => array( - 'type' => 'boolean', - 'label' => t('Tree'), - 'description' => t('Used to allow collections of form elements. Normally applied to the "parent" element, as the #tree property cascades to sub-elements.'), - 'attribute info' => array('elements' => 'all', 'read only' => TRUE), - ), - '#type' => array( - 'type' => 'text', - 'label' => t('Element type'), - 'attribute info' => array('elements' => 'all', 'read only' => TRUE), - 'required' => TRUE, - ), - '#weight' => array( - 'type' => 'integer', - 'label' => t('Weight'), - 'description' => t('Used to sort the list of form elements before being output; lower numbers appear before higher numbers.'), - 'attribute info' => array('elements' => 'all'), - ), - '#value' => array( - 'type' => '*', - 'label' => t('Value'), - 'attribute info' => array( - 'read only' => TRUE, - 'elements' => array('value', 'hidden'), - ), - ), - ); -} + t('Button'), + 'properties' => rules_forms_element_properties('button'), + 'element info' => array( + 'data type' => 'text', + 'keys' => array('value' => '#value'), + 'empty' => '', + ), + ); + $info['checkbox'] = array( + 'label' => t('Checkbox'), + 'properties' => rules_forms_element_properties('checkbox'), + 'element info' => array( + 'data type' => 'boolean', + 'keys' => array('value' => '#value', 'default_value' => '#default_value'), + 'empty' => FALSE, + ), + ); + $info['checkboxes'] = array( + 'label' => t('Checkboxes'), + 'properties' => rules_forms_element_properties('checkboxes'), + 'element info' => array( + 'data type' => 'struct', + 'keys' => array('value' => '#value', 'default_value' => '#default_value'), + 'empty' => array(), + ), + ); + $info['container'] = array( + 'label' => t('Container'), + 'properties' => rules_forms_element_properties('container'), + // The 'data type' FALSE indicates that this element is not settable. + 'element info' => array('data type' => FALSE), + ); + $info['fieldset'] = array( + 'label' => t('Fieldset'), + 'properties' => rules_forms_element_properties('fieldset'), + // The 'data type' FALSE indicates that this element is not settable. + 'element info' => array('data type' => FALSE), + ); + $info['hidden'] = array( + 'label' => t('Hidden'), + 'properties' => rules_forms_element_properties('hidden'), + 'element info' => array( + 'data type' => '*', + 'keys' => array('value' => '#value'), + 'empty' => NULL, + ), + ); + $info['item'] = array( + 'label' => t('Item'), + 'properties' => rules_forms_element_properties('item'), + 'element info' => array( + 'data type' => 'text', + 'keys' => array('value' => '#markup'), + 'empty' => '', + ), + ); + $info['markup'] = array( + 'label' => t('Markup'), + 'properties' => rules_forms_element_properties('markup'), + 'element info' => array( + 'data type' => 'text', + 'keys' => array('value' => '#markup'), + 'empty' => '', + ), + ); + $info['password'] = array( + 'label' => t('Password'), + 'properties' => rules_forms_element_properties('password'), + 'element info' => array( + 'data type' => 'text', + 'keys' => array('value' => '#value'), + 'empty' => NULL, + ), + ); + $info['radio'] = array( + 'label' => t('Radio'), + 'properties' => rules_forms_element_properties('radio'), + 'element info' => array( + 'data type' => 'text', + 'keys' => array('value' => '#value', 'default_value' => '#default_value'), + 'empty' => NULL, + ), + ); + $info['radios'] = array( + 'label' => t('Radios'), + 'properties' => rules_forms_element_properties('radios'), + 'element info' => array( + 'data type' => 'text', + 'keys' => array('value' => '#value', 'default_value' => '#default_value'), + 'empty' => '', + ), + ); + $info['select'] = array( + 'label' => t('Select list'), + 'properties' => rules_forms_element_properties('select'), + 'element info' => array( + 'data type' => 'text|struct', + 'keys' => array('value' => '#value', 'default_value' => '#default_value'), + 'empty' => '', + ), + ); + $info['submit'] = array( + 'label' => t('Submit'), + 'properties' => rules_forms_element_properties('submit'), + 'element info' => array( + 'data type' => 'text', + 'keys' => array('value' => '#value'), + 'empty' => '', + ), + ); + $info['tableselect'] = array( + 'label' => t('Table select list'), + 'properties' => rules_forms_element_properties('tableselect'), + 'element info' => array( + 'data type' => 'struct', + 'keys' => array('value' => '#value', 'default_value' => '#default_value'), + 'empty' => array(), + ), + ); + $info['text_format'] = array( + 'label' => t('Text format'), + 'properties' => rules_forms_element_properties('text_format'), + 'element info' => array( + 'data type' => 'text', + 'keys' => array('value' => '#value', 'default_value' => '#default_value'), + 'empty' => '', + ), + ); + $info['textarea'] = array( + 'label' => t('Text area'), + 'properties' => rules_forms_element_properties('textarea'), + 'element info' => array( + 'data type' => 'text', + 'keys' => array('value' => '#value', 'default_value' => '#default_value'), + 'empty' => '', + ), + ); + $info['textfield'] = array( + 'label' => t('Text field'), + 'properties' => rules_forms_element_properties('textfield'), + 'element info' => array( + 'data type' => 'text', + 'keys' => array('value' => '#value', 'default_value' => '#default_value'), + 'empty' => '', + ), + ); + $info['weight'] = array( + 'label' => t('Weight'), + 'properties' => rules_forms_element_properties('weight'), + 'element info' => array( + 'data type' => 'integer', + 'keys' => array('value' => '#value', 'default_value' => '#default_value'), + 'empty' => 0, + ), + ); + $info['value'] = array( + 'label' => t('Value'), + 'properties' => rules_forms_element_properties('value'), + 'element info' => array( + 'data type' => '*', + 'keys' => array('value' => '#value'), + 'empty' => '', + ), + ); + return $info; +} + +/** + * Returns an array of attribute property info for a specific form element type. + * + * @param string $element_type + * The form element type. This is an element type defined in + * hook_rules_forms_element_info(). + */ +function rules_forms_element_properties($element_type) { + $attribute_info = _rules_forms_attribute_info(); + $attributes = array(); + foreach ($attribute_info as $attribute => $info) { + if ($info['attribute info']['elements'] == 'all' || in_array($element_type, $info['attribute info']['elements'])) { + $attributes[$attribute] = _rules_forms_build_element_property($info); + } + } + return $attributes; +} + +/** + * Returns an array of element properties based on existing attributes. + */ +function rules_forms_filter_element_properties($element) { + $attribute_info = _rules_forms_attribute_info(); + $attributes = array(); + foreach (element_properties($element) as $attribute => $info) { + if (isset($attribute_info[$attribute])) { + $attributes[$attribute] = _rules_forms_build_element_property($info); + } + } + return $attributes; +} + +/** + * Builds the property info of an individual property from an array of info. + */ +function _rules_forms_build_element_property(array $info) { + $info += array( + 'getter callback' => 'entity_property_verbatim_get', + 'computed' => TRUE, + 'attribute info' => array(), + ); + $info['attribute info'] += array('read only' => FALSE); + if (empty($info['attribute info']['read only'])) { + $info += array('setter callback' => 'entity_property_verbatim_set'); + } + // Unset the 'elements' and 'read only' portions as those are not used in + // wrappers. + unset($info['attribute info']['elements'], $info['attribute info']['read only']); + return $info; +} + +/** + * Retrive a list of Form API properties with supported attributes information. + */ +function _rules_forms_attribute_info() { + return array( + '#access' => array( + 'type' => 'boolean', + 'label' => t('Visible'), + 'description' => t('Whether the element is accessible or not; when FALSE, the element is not rendered and the user submitted value is not taken into consideration.'), + 'attribute info' => array('elements' => 'all'), + ), + '#collapsed' => array( + 'type' => 'boolean', + 'label' => t('Collapsed'), + 'description' => t('Indicates whether or not the fieldset is collapsed by default.'), + 'attribute info' => array('elements' => array('fieldset')), + ), + '#collapsible' => array( + 'type' => 'boolean', + 'label' => t('Collapsible'), + 'description' => t('Indicates whether or not the fieldset can be collapsed with JavaScript.'), + 'attribute info' => array('elements' => array('fieldset')), + ), + '#cols' => array( + 'type' => 'int', + 'label' => t('Columns'), + 'description' => t('How many columns wide the textarea should be.'), + 'attribute info' => array('elements' => array('text_format', 'textarea')), + ), + '#default_value' => array( + 'type' => 'text', + 'label' => t('Default value'), + 'description' => t('The value of the form element that will be displayed or selected initially if the form has not been submitted yet.'), + 'attribute info' => array( + 'elements' => array( + 'checkbox', + 'checkboxes', + 'hidden', + 'radio', + 'radios', + 'select', + 'tableselect', + 'text_format', + 'textarea', + 'textfield', + 'weight', + ), + ), + ), + '#description' => array( + 'type' => 'text', + 'label' => t('Description'), + 'description' => t('The description of the form element.'), + 'attribute info' => array( + 'elements' => array('checkbox', + 'checkboxes', + 'hidden', + 'item', + 'password', + 'radio', + 'radios', + 'select', + 'tableselect', + 'text_format', + 'textarea', + 'textfield', + 'weight', + ), + ), + ), + '#disabled' => array( + 'type' => 'boolean', + 'label' => t('Disabled'), + 'description' => t('Disables (greys out) a form input element.'), + 'attribute info' => array( + 'elements' => array('button', + 'checkbox', + 'checkboxes', + 'password', + 'radio', + 'radios', + 'select', + 'submit', + 'text_format', + 'textarea', + 'textfield', + 'weight', + 'text_format', + ), + ), + ), + '#field_prefix' => array( + 'type' => 'text', + 'label' => t('Field prefix text or HTML'), + 'sanitize' => 'check_markup', + 'description' => t('Text or code that is placed directly in front of the textfield.'), + 'attribute info' => array( + 'elements' => array('checkbox', + 'radio', + 'select', + 'textarea', + 'textfield', + ), + ), + ), + '#field_suffix' => array( + 'type' => 'text', + 'label' => t('Field suffix text or HTML'), + 'sanitize' => 'check_markup', + 'description' => t('Text or code that is placed directly after the textfield.'), + 'attribute info' => array( + 'elements' => array('checkbox', + 'radio', + 'select', + 'textarea', + 'textfield', + ), + ), + ), + '#markup' => array( + 'type' => 'text', + 'label' => t('HTML'), + 'sanitize' => 'check_markup', + 'description' => t('Used to set HTML that will be output on the form.'), + 'attribute info' => array('elements' => array('item', 'markup')), + ), + '#multiple' => array( + 'type' => 'boolean', + 'label' => t('Allow multiple'), + 'description' => t('Indicates whether the user may select more than one item.'), + 'attribute info' => array( + 'elements' => array('select'), + 'read only' => TRUE, + ), + ), + '#name' => array( + 'type' => 'text', + 'label' => t('Name'), + 'description' => t('The form element name. This can be used as an identifer.'), + 'attribute info' => array('elements' => array('button', 'submit')), + ), + '#options' => array( + 'type' => 'text', + 'label' => t('Options'), + 'description' => t('Selectable options for a form element that allows multiple choices.'), + 'attribute info' => array( + 'elements' => array('select', 'checkboxes', 'radios', 'tableselect'), + 'validate callback' => 'rules_forms_options_set_validate', + 'setter callback' => 'rules_forms_options_set', + ), + ), + '#prefix' => array( + 'type' => 'text', + 'label' => t('Prefix text or HTML'), + 'description' => t('Text or markup to include before the form element.'), + 'attribute info' => array('elements' => 'all'), + ), + '#required' => array( + 'type' => 'boolean', + 'label' => t('Required'), + 'description' => t('Indicates whether or not the element is required. This automatically validates for empty fields, and flags inputs as required.'), + 'attribute info' => array( + 'elements' => array('checkbox', + 'checkboxes', + 'password', + 'radio', + 'radios', + 'select', + 'textarea', + 'text_format', + 'textfield', + 'weight', + ), + ), + ), + '#resizable' => array( + 'type' => 'boolean', + 'label' => t('Resizable'), + 'description' => t('Indicates whether users should be allowed to resize the text area.'), + 'attribute info' => array('elements' => array('text_format', 'textarea')), + ), + '#rows' => array( + 'type' => 'int', + 'label' => t('Rows'), + 'description' => t('How many rows high the textarea should be.'), + 'attribute info' => array('elements' => array('text_format', 'textarea')), + ), + '#size' => array( + 'type' => 'int', + 'label' => t('Size'), + 'description' => t('Width of the textfield (in characters) or size of multiselect box (in lines).'), + 'attribute info' => array( + 'elements' => array('select', + 'password', + 'textfield', + ), + ), + ), + '#suffix' => array( + 'type' => 'text', + 'label' => t('Suffix text or HTML'), + 'description' => t('Text or markup to include after the form element.'), + 'attribute info' => array('elements' => 'all'), + ), + '#title' => array( + 'type' => 'text', + 'label' => t('Title'), + 'description' => t('The title of the form element.'), + 'attribute info' => array( + 'elements' => array('button', + 'checkbox', + 'checkboxes', + 'password', + 'radio', + 'radios', + 'select', + 'submit', + 'text_format', + 'textarea', + 'textfield', + 'weight', + 'text_format', + 'item', + ), + ), + ), + '#tree' => array( + 'type' => 'boolean', + 'label' => t('Tree'), + 'description' => t('Used to allow collections of form elements. Normally applied to the "parent" element, as the #tree property cascades to sub-elements.'), + 'attribute info' => array('elements' => 'all', 'read only' => TRUE), + ), + '#type' => array( + 'type' => 'text', + 'label' => t('Element type'), + 'attribute info' => array('elements' => 'all', 'read only' => TRUE), + 'required' => TRUE, + ), + '#weight' => array( + 'type' => 'integer', + 'label' => t('Weight'), + 'description' => t('Used to sort the list of form elements before being output; lower numbers appear before higher numbers.'), + 'attribute info' => array('elements' => 'all'), + ), + '#value' => array( + 'type' => '*', + 'label' => t('Value'), + 'attribute info' => array( + 'read only' => TRUE, + 'elements' => array('value', 'hidden'), + ), + ), + ); +} diff --git a/includes/rules_forms.property.inc b/includes/rules_forms.property.inc index 0cd5bca..acdabbd 100644 --- a/includes/rules_forms.property.inc +++ b/includes/rules_forms.property.inc @@ -1,16 +1,27 @@ elementInfo = rules_forms_get_element_info(); } /** - * Evaluates the elements of a form to identify its structure in property info. + * Evaluates form elements to identify its structure in property info. * * @param array $form * The form array to evaluate. @@ -68,13 +79,14 @@ class RulesFormsFormEvaluator { if (isset($form[$key]['#type']) && array_key_exists($form[$key]['#type'], $this->elementInfo)) { $info = $this->elementInfo[$form[$key]['#type']]; $defaults = array( - 'label' => isset($form[$key]['#title']) ? $info['label'] .': '. $form[$key]['#title'] : $info['label'], + 'label' => isset($form[$key]['#title']) ? $info['label'] . ': ' . $form[$key]['#title'] : $info['label'], 'computed' => TRUE, 'auto creation' => 'rules_forms_create_structure', 'getter callback' => 'entity_property_verbatim_get', ); - - // All form elements are structures since they have attribute property info. + + // All form elements are structures since they have attribute property + // info. $form_properties[$key] = $defaults + array( 'type' => 'form_' . $form[$key]['#type'], 'setter callback' => 'entity_property_verbatim_set', @@ -84,10 +96,10 @@ class RulesFormsFormEvaluator { ), 'property info' => $info['properties'], ); - + $is_tree = ($tree == TRUE || !empty($form[$key]['#tree'])); $form_state_properties[$key] = $defaults; - + // If this is a tree then property info needs to be stored as such. $children = element_children($form[$key]); if ($is_tree && !empty($children)) { @@ -101,8 +113,9 @@ class RulesFormsFormEvaluator { } $this->buildPropertyInfo($form[$key], $form_properties[$key]['property info'], $form_state_arg, $is_tree); } - // Handle cases where an array is not necessarily a form element with a #type. - // We just identify it as a 'struct' with no properties except the sub arrays. + // Handle cases where an array is not necessarily a form element with a + // #type. We just identify it as a 'struct' with no properties except the + // sub arrays. elseif (!isset($form[$key]['#type'])) { $defaults = array( 'type' => 'form_element', @@ -111,7 +124,8 @@ class RulesFormsFormEvaluator { 'auto creation' => 'rules_forms_create_structure', 'getter callback' => 'entity_property_verbatim_get', ); - // In this case, properties are filtered based on the attributes that are available. + // In this case, properties are filtered based on the attributes that + // are available. $form_properties[$key] = $defaults + array( 'setter callback' => 'entity_property_verbatim_set', 'element info' => array( diff --git a/includes/rules_forms.wrapper.inc b/includes/rules_forms.wrapper.inc index 217582e..033a5f1 100644 --- a/includes/rules_forms.wrapper.inc +++ b/includes/rules_forms.wrapper.inc @@ -1,8 +1,13 @@ array()); $info['element info'] += array('data type' => 'text'); @@ -155,12 +167,14 @@ class RulesFormsElementWrapper extends RulesFormsStructureWrapper { } /** - * Returns the current value of the form element either from #value or #default_value. - * If neither of these is set we use the 'empty value' key. + * Returns the current value of the form element. + * + * Valeu is taken either from #value or #default_value. If neither is set we + * use the 'empty value' key. * * @return mixed - * The element value retrieved from defined keys. If neither the value or default value - * is defined, the empty value will be returned. + * The element value retrieved from defined keys. If neither the value or + * default value is defined, the empty value will be returned. * * @throws EntityMetadataWrapperException * The form element does not contain a value. @@ -215,7 +229,7 @@ class RulesFormsElementWrapper extends RulesFormsStructureWrapper { * The form element does not support a default value. */ public function setElementDefaultValue($value) { - if ($this->info['element info']['data type'] == FALSE || $default_value_key = $this->getElementKey('default_value') === FALSE) { + if ($this->info['element info']['data type'] == FALSE || $default_value_key = $this->getElementKey('default_value') === FALSE) { throw new EntityMetadataWrapperException('Form element ' . check_plain($this->info['name']) . ' does not support a default value.'); } else { @@ -225,7 +239,7 @@ class RulesFormsElementWrapper extends RulesFormsStructureWrapper { } /** - * Returns the value of the form element when #value and #default_value are not set. + * Returns the form element value when #value and #default_value are not set. */ public function getElementEmptyValue() { return $this->info['element info']['empty']; @@ -239,8 +253,10 @@ class RulesFormsElementWrapper extends RulesFormsStructureWrapper { class RulesFormsAttributeWrapper extends EntityValueWrapper { /** - * Magic method: Retrieve data from parent form element by calling - * getElement* methods directly. Setter methods are not supported here. + * Magic method: Retrieve data from parent form element. + * + * This is done by calling getElement methods directly. Setter methods are not + * supported. */ public function __call($method, array $args) { if (substr($method, 0, 10) === 'getElement' && method_exists($this->info['parent'], $method)) { @@ -249,16 +265,17 @@ class RulesFormsAttributeWrapper extends EntityValueWrapper { } /** - * Overrides EntityMetadataWrapper::set() to handle special circumstances - * of form attributes. + * Overrides EntityMetadataWrapper::set(). + * + * Handles special circumstances of form attributes. */ public function set($value) { - // The #options attribute is identified in property info as a 'text' property - // in order to provide the proper interface. However, that text is converted - // to an array, so if this is an #options attribute we just check to ensure that - // we're either receiving text or an array. + // The #options attribute is identified in property info as a 'text' + // property in order to provide the proper interface. However, that text is + // converted to an array, so if this is an #options attribute we just check + // to ensure that we're either receiving text or an array. if ($this->info['name'] == '#options') { - if (!is_string($value) && !is_array($value)) { + if (!is_string($value) && !is_array($value)) { throw new EntityMetadataWrapperException('Invalid data value given. Be sure it matches the required data type and format.'); } } diff --git a/rules_forms.install b/rules_forms.install old mode 100755 new mode 100644 diff --git a/rules_forms.module b/rules_forms.module old mode 100755 new mode 100644 diff --git a/rules_forms.rules.inc b/rules_forms.rules.inc old mode 100755 new mode 100644