You are here

function patterns_sync_form_values in Patterns 7.2

Same name and namespace in other branches
  1. 6.2 patterns.module \patterns_sync_form_values()
  2. 6 patterns.module \patterns_sync_form_values()
  3. 7 includes/unused.inc \patterns_sync_form_values()

Make some modifications to the form values based on the form In particular, make sure form elements with #options and #multiple set the keys of the array as the key of the value as how FAPI does it, but XML of course does not.

File

includes/unused.inc, line 113
Functions that are unused at the moment.

Code

function patterns_sync_form_values($args) {
  $form_id = $args[0];

  // this functionality is not working well with
  // node forms (create/update node)
  // so skip them until this issue is fixed
  if (strpos($form_id, 'node_form') !== FALSE) {
    return;
  }

  // References inside the form_state can cause potential problems,
  // so we'll ensure no references to outside data exists
  $form_state = unserialize(serialize($args[1]));
  $form_values = $form_state['values'];
  unset($args[1]['values']);

  // Get the fully built fapi object with cloned form_state.
  // We need to do this with a separate form_state because
  // this can mess up the form values if they are setup incorrectly
  // (it'll get fixed here)
  $form = call_user_func_array('drupal_retrieve_form', $args);
  drupal_prepare_form($form_id, $form, $form_state);
  $form = form_builder($form_id, $form, $form_state);

  // Loop through all form values looking for #options
  $queue = array(
    &$form,
  );
  while (!empty($queue)) {
    $check =& $queue[0];
    array_shift($queue);

    // Skip disabled items
    if ($check['#disabled']) {
      continue;
    }

    // Set default values for everything that the form is expecting values for.
    // This can save work in the components as well as avoid bugs when a module
    // expects values to be there that are not.
    // Do not set default values when it is the type of value that a form submit
    // would not set data in $_POST for. Like selects with no options or unchecked
    // checkboxes
    if ($check['#input'] && isset($check['#default_value']) && !($check['#type'] == 'select' && empty($check['#options'])) && !(in_array($check['#type'], array(
      'checkbox',
      'checkboxes',
    )) && empty($check['#default_value']))) {
      $match =& $form_values;
      $found = TRUE;
      foreach ($check['#parents'] as $path) {
        if (!isset($match[$path])) {
          $found = FALSE;
          $match[$path] = array();
        }

        // If this is not an array, the data was probably not completed properly
        // in the pattern.
        if (!is_array($match)) {
          $message = t('Invalid pattern syntax at: !path. Expecting more child elements.', array(
            '!path' => implode('->', $check['#parents']),
          ));
          patterns_error_handler(1, $message, '', '');
          return;
        }
        $match =& $match[$path];
      }

      // Set the default value unless it is a type of value that would originally
      // not be set in $_POST during form submit, like empty selects
      if (!$found) {
        $check['#missing_in_pattern'] = TRUE;
        $match = $check['#default_value'];
      }
    }
    if (!empty($check['#options'])) {
      $scalar = FALSE;
      if (!$check['#tree'] && !$check['#multiple'] || isset($check['#multiple']) && !$check['#multiple'] || in_array($check['#type'], array(
        'radio',
        'radios',
      ))) {
        $scalar = TRUE;
      }

      // Find possible corresponding data in form values
      $match =& $form_values;
      $found = TRUE;
      foreach ($check['#parents'] as $path) {
        if (isset($match[$path])) {
          $match =& $match[$path];
        }
        else {
          $found = FALSE;
          break;
        }
      }
      if ($found && isset($match)) {

        // Check if we are overwriting or not.
        //
        // First, if the pattern value is there, but empty, we obviously
        // should be overwriting. Next is to check if overwrite was specified
        // manually
        $overwrite = FALSE;
        if (!$check['#missing_in_pattern'] && (empty($match) || is_array($match) && !empty($match['overwrite']))) {
          $overwrite = TRUE;
          if (is_array($match) && isset($match['overwrite'])) {
            unset($match['overwrite']);
          }
        }
        $delete = FALSE;
        if (is_array($match) && !empty($match['delete'])) {
          $delete = TRUE;
          unset($match['delete']);
        }

        // If overwriting, start the values array with all the
        // possible values but empty. We will possibly fill them
        // in with default values on update actions. Select types
        // do not work when empty, non-selected, values are set
        if (!$scalar && $overwrite && $check['#type'] != 'select') {
          $values = $check['#options'];
          foreach ($values as &$v) {
            $v = '';
          }
        }
        else {
          $values = array();
        }
        if (!$overwrite && !empty($check['#default_value'])) {
          foreach ((array) $check['#default_value'] as $value) {
            $values[$value] = $value;
          }

          // Make sure we are still restricted to values available in #options
          $values = array_intersect_key($values, $check['#options']);
        }

        // Flatten out the options in case it is trying to use optgroups
        $options = patterns_options_flatten($check['#options']);
        foreach ((array) $match as $value) {
          $key = array_search($value, $options);

          // If the supplied value is an actual options value (not the label) use that
          if ((is_string($value) || is_int($value)) && array_key_exists($value, $options)) {
            $values[$value] = $delete ? 0 : $value;
          }
          elseif ($key !== FALSE) {
            $values[$key] = $delete ? 0 : $key;
          }
          elseif ($check['#type'] == 'select') {
            reset($options);
            $values[key($options)] = key($options);
          }
        }

        // If we are not on a multiple/tree form, the value should be singular/not an array.
        // We make sure to use the last value here because the last value will absolutely
        // be the user/pattern supplied value as opposed to the default_value
        if ($scalar) {
          $match = end($values);
        }
        else {
          $match = $values;
        }
      }
    }
    foreach (element_children($check) as $element) {
      $queue[] =& $check[$element];
    }
  }

  // Make sure the new form_values will be used in the real executions
  $args[1]['values'] = $form_values;
}