diff --git a/modules/data.eval.inc b/modules/data.eval.inc index 3e0b77e..8d4b5af 100644 --- a/modules/data.eval.inc +++ b/modules/data.eval.inc @@ -169,6 +169,48 @@ function rules_action_variable_add_info_alter(&$element_info, RulesAbstractPlugi } /** + * Action: Convert a value. + */ +function rules_action_data_convert($from_type, $input, $to_type, $rounding_behavior, $settings, $state, $element) { + switch ($from_type) { + case 'decimal': + switch($to_type) { + case 'integer': + //First apply the rounding behavior + $result = round($input, 0, constant($rounding_behavior)); + //Convert the value to int + $result = (int) $result; + break; + } + case 'integer': + switch($to_type) { + case 'decimal' : + $result = (float) $input; + break; + } + } + return array('conversion_result' => $result); +} + +/** + * Info alteration callback for variable add action. + */ +function rules_action_data_convert_info_alter(&$element_info, RulesAbstractPlugin $element) { + + if (isset($element->settings['to_type']) && $to_type = $element->settings['to_type']) { + $cache = rules_get_cache(); + $type_info = $cache['data_info'][$to_type]; + $element_info['provides']['conversion_result']['type'] = $to_type; + } + + if (isset($element->settings['from_type']) && $from_type = $element->settings['from_type']) { + $cache = rules_get_cache(); + $type_info = $cache['data_info'][$from_type]; + $element_info['parameter']['input']['type'] = $from_type; + } +} + +/** * Action: Create data. */ function rules_action_data_create($args, $element) { diff --git a/modules/data.rules.inc b/modules/data.rules.inc index a1ab9fe..205e026 100644 --- a/modules/data.rules.inc +++ b/modules/data.rules.inc @@ -192,10 +192,161 @@ function rules_data_action_info() { ), ); } + $return['data_convert'] = array( + 'label' => t('Convert data type'), + 'parameter' => array( + 'from_type' => array( + 'type' => 'text', + 'label' => t('Conversion type (from)'), + 'description' => t('The type of data to convert from.'), + 'options list' => 'rules_action_data_convert_types_options', + 'restriction' => 'input', + 'default value' => '', + ), + 'input' => array( + 'type' => array('decimal', 'integer'), + 'label' => t('Value to convert'), + 'description' => t('The value to convert.'), + ), + 'to_type' => array( + 'type' => 'text', + 'label' => t('Conversion type (to)'), + 'description' => t('The conversion type expected.'), + 'options list' => 'rules_action_data_convert_types_options', + 'restriction' => 'input', + 'default value' => '', + ), + 'rounding_behavior' => array( + 'type' => 'text', + 'label' => t('Rounding behavior (for Decimal value to Int conversion)'), + 'description' => t('The rounding behavior the conversion should use.'), + 'options list' => 'rules_action_data_convert_rounding_behavior_options', + 'restriction' => 'input', + 'default value' => 'PHP_ROUND_HALF_UP', + 'allow null' => TRUE, + 'optional' => TRUE, + ), + ), + 'provides' => array( + 'conversion_result' => array( + 'type' => 'unknown', + 'label' => t('Conversion result'), + ), + ), + 'group' => t('Data'), + 'base' => 'rules_action_data_convert', + 'callbacks' => array( + 'form_alter' => 'rules_action_data_convert_form_alter', + 'validate' => 'rules_action_data_convert_validate', + ), + ); return $return; } /** + * Custom validate callback for data convert action. + */ +function rules_action_data_convert_validate(RulesAbstractPlugin $element) { + if (!isset($element->settings['from_type'])) { + throw new RulesIntegrityException(t('"From" type is empty.'), array($element, 'parameter', 'from_type')); + } + if (!isset($element->settings['to_type'])) { + throw new RulesIntegrityException(t('"To" type is empty.'), array($element, 'parameter', 'to_type')); + } +} + +/** + * Options list callback for the data conversion action. + */ +function rules_action_data_convert_types_options(RulesPlugin $element, $param_name) { + $options = array( + '' => '- Select -', + 'decimal' => 'Decimal', + 'integer' => 'Integer', + ); + return $options; +} + +/** + * Options list callback for rounding behavior in data conversion action. + */ +function rules_action_data_convert_rounding_behavior_options(RulesPlugin $element, $param_name) { + $options = array( + 'PHP_ROUND_HALF_UP' => 'Round half up (9.5 -> 10)', + 'PHP_ROUND_HALF_DOWN' => 'Round half down (9.5 -> 9)', + 'PHP_ROUND_HALF_EVEN' => 'Round half even (9.5 -> 10)', + 'PHP_ROUND_HALF_ODD' => 'Round half odd (9.5 -> 9)', + ); + return $options; +} + +/** + * Form alter callback for actions relying on the entity type or the data type. + */ +function rules_action_data_convert_form_alter(&$form, &$form_state, $options, RulesAbstractPlugin $element) { + //Define at which step we are in the action configuration process + if(empty($element->settings['from_type'])) { + $current_step = 1; + $form_reload_value = t('Continue'); + $limit_validation_errors = array(array('parameter', 'from_type')); + } + else { + $current_step = 2; + $form_reload_value = t('Continue'); + $limit_validation_errors = array(array('parameter', 'from_type'), array('parameter', 'input'), array('parameter', 'to_type')); + } + + //Build the form reload button + $form['reload'] = array( + '#weight' => 5, + '#type' => 'submit', + '#name' => 'reload', + '#value' => $form_reload_value, + '#limit_validation_errors' => $limit_validation_errors, + '#submit' => array('rules_action_type_form_submit_rebuild'), + '#ajax' => rules_ui_form_default_ajax(), + ); + + // Use ajax and trigger as the reload button. + $form['parameter']['from_type']['settings']['from_type']['#ajax'] = $form['reload']['#ajax'] + array( + 'event' => 'change', + 'trigger_as' => array('name' => 'reload'), + ); + + switch($current_step) { + case 1: + // In the first step show only the type select. + foreach (element_children($form['parameter']) as $key) { + if ($key != 'from_type') { + unset($form['parameter'][$key]); + } + } + unset($form['submit']); + unset($form['provides']); + break; + case 2: + // In the second step show only from_type, input_value, to_type + foreach (element_children($form['parameter']) as $key) { + if ($key != 'from_type' && $key != 'input' && $key != 'to_type') { + //If the from_type is not decimal, we don't need to ask this parameter + if($key == 'rounding_behavior' && $element->settings['from_type'] == 'decimal') + continue; + unset($form['parameter'][$key]); + } + } + + //Force the input parameter field to the "from" data type + $form['parameter']['input']['settings']['help']['#parameter']['type'] = $element->settings['from_type']; + + //Unset the to_type defined by from_type (prevent decimal -> decimal or int -> int conversion) + unset($form['parameter']['to_type']['settings']['to_type']['#options'][$element->settings['from_type']]); + + $form['reload']['#attributes'] = array('class' => array('rules-hide-js')); + break; + } +} + +/** * Customize access check for data set action. */ function rules_action_data_set_access(RulesAbstractPlugin $element) {