<?php
/**
 * @file
 * Change textfield webform component to select options from nodetype fields.
 */

/**
 * Implements hook_help().
 */
function webform_select_opts_help($path, $arg) {
  switch ($path) {
    case 'admin/config/content/webform/wfso':
      $output = t('First step: enable content type here. Fields on enabled content types are avalable in Second step: Set Field setting on tab "Select opts fields settings".');
      return $output;
    case 'admin/config/content/webform/wfso/fields_setting':
      $output = t('Settings to source for webform component data. Option VALUE is sending as data of the user choose by webform, Option TEXT is a Label of this component. "Option TEXT" and "Option VALUE" field must contain one (1) value - don\'t use field with multiple values or term like tags.');
      return $output;
  }
}

/**
 * Implements hook_menu().
 */
function webform_select_opts_menu() {

  $items['admin/config/content/webform/wfso'] = array(
    'title' => 'Webform Select options settings',
    'description' => 'Settings for webform Select options source',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('node_types_wfso_avalable_settings'),
    'access arguments' => array('administer site configuration'),
    'type' => MENU_NORMAL_ITEM,
  );
  $items['admin/config/content/webform/wfso/webform_select_opts_settings'] = array(
    'title' => 'Webform Select options settings',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('node_types_wfso_avalable_settings'),
    'access arguments' => array('administer site configuration'),
    'type' => MENU_LOCAL_TASK,
    'weight' => 0,
  );
  $items['admin/config/content/webform/wfso/webform_select_opts_settings'] = array(
    'title' => 'Webform Select options settings',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('node_types_wfso_avalable_settings'),
    'access arguments' => array('administer site configuration'),
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'weight' => 0,
  );

  $items['admin/config/content/webform/wfso/fields_setting'] = array(
    'title' => 'Select opts fields settings',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('node_types_wfso_fields_settings'),
    'access arguments' => array('administer site configuration'),
    'type' => MENU_LOCAL_TASK,
    'weight' => 1,
  );

  return $items;
}

/**
 *  Settings form for the fields of avalable node types
 */
function node_types_wfso_fields_settings() {
  $form = array();
  $node_types = node_type_get_types();
  $fields_ct = field_info_instances('node');

  $form['#tree'] = TRUE;

  foreach ($node_types AS $n_type) {

    if (variable_get('webform_select_options_for_' . $n_type -> type, 0)) {
      $options = array();

      foreach ($fields_ct[$n_type -> type] AS $fields) {
        if ($fields['label'] == 'Body') {
          continue;
        }
        else {
          $options[$fields['field_name']] = $fields['label'];
        }
      }
      
      $variable_value = variable_get('webform_select_options_fields_' . $n_type -> type, '');
      $fields_names = unserialize($variable_value);
      
      $form['webform_select_options_ntypes'][$n_type -> type] = array(
        '#type' => 'fieldset',
        '#title' => t('@ntype\'s Fields settings', array('@ntype' => $n_type -> name)),
        '#description' => t('Fields of node type @type to construct select options in webform.', array('@type' => drupal_strtoupper($n_type -> name))),
        '#collapsible' => TRUE,
        '#collapsed' => FALSE,
        '#weight' => -1
      );
      $form['webform_select_options_ntypes'][$n_type -> type]['node_type'] = array(
        '#type' => 'hidden',
        '#value' => $n_type -> type,
      );
      $form['webform_select_options_ntypes'][$n_type -> type]['select_value'] = array(
        '#type' => 'select',
        '#title' => t('Option VALUE'),
        '#description' => t('The value of this field will send by form!'),
        '#options' => $options,
        '#default_value' => $fields_names[0],
      );
      $form['webform_select_options_ntypes'][$n_type -> type]['select_value_is_wfso_field'] = array(
        '#type' => 'checkbox',
        '#title' => t('Field VALUE is e-mail address'),
        '#default_value' => $fields_names[2],
      );
      $form['webform_select_options_ntypes'][$n_type -> type]['select_text'] = array(
        '#type' => 'select',
        '#attributes' => array('disabled' => 'disabled'),
        '#title' => t('Option TEXT'),
        '#options' => array('node_title' => t('Node title')),
        '#default_value' => 'node_title',
      );
    }
  }
  
  $form['#submit'][] = 'webform_select_options_fields_settings_submit';

  return system_settings_form($form);
}

function webform_select_options_fields_settings_submit($form, &$form_state) {
  
  foreach ($form_state['input']['webform_select_options_ntypes'] AS $n_type => $val) {
    $variable_value = serialize(array($val['select_value'], $val['select_text'], $val['select_value_is_wfso_field']));
    variable_set('webform_select_options_fields_' . $n_type, $variable_value);
  }
}

/**
 * Settings form for avalable node types to create Search&Location block for webforms with its fields
 */
function node_types_wfso_avalable_settings() {
  $form = array();

  $node_types = node_type_get_types();
  
  $form['#tree'] = TRUE;
  $form['webform_select_options'] = array(
    '#type' => 'fieldset',
    '#title' => t('Webform select options source'),
    '#description' => t('Enable content type for webform component source.'),
    '#collapsible' => TRUE,
    '#collapsed' => FALSE,
    '#weight' => -1
  );
  
  foreach ($node_types AS $n_type) {
    $form['webform_select_options'][$n_type -> type] = array(
      '#type' => 'checkbox',
      '#title' => $n_type -> name,
      '#default_value' => variable_get('webform_select_options_for_' . $n_type -> type, 0),
    );
  }
  
  $form['#submit'][] = 'webform_select_options_node_types_submit';

  return system_settings_form($form);
}

function webform_select_options_node_types_submit($form, &$form_state) {
  foreach ($form_state['input']['webform_select_options'] AS $n_type => $val) {
    if ($val) {
      variable_set('webform_select_options_for_' . $n_type, $val);
    }
    else {
      variable_del('webform_select_options_for_' . $n_type);
      variable_del('webform_select_options_fields_' . $n_type);
    }
  }
}

/**
 * Implements hook_form_FORM_ID_alter();
 */
function webform_select_opts_form_webform_emails_form_alter(&$form, &$form_state, $form_id) {
  //ToDo: get field nid cid to unset it if not email
}

/**
 * Implements hook_form_FORM_ID_alter();
 */
function webform_select_opts_form_webform_client_form_alter(&$form, &$form_state, $form_id) {
  foreach ($form['submitted'] AS $input) {
    if ($input['#webform_component']['type'] == ('textfield')) {
      
      $nid = $input['#webform_component']['nid'];
      $cid = $input['#webform_component']['cid'];
      
      $n_type = db_select('webform_select_opts_component', 's')
        -> fields('s', array('data'))
        -> condition('nid', $nid, '=')
        -> condition('cid', $cid, '=')
        -> execute() -> fetchField();
      
      if ($n_type) {
        $var = variable_get('webform_select_options_fields_' . $n_type, '');
        $field_val = unserialize($var);
        
        if ($var) {
          if ($field_val[0] == 'node_title') {
            $query = db_select('node', 'n');
            $query -> fields('n', array('nid', 'title'));
            $query -> condition('n.type', $n_type, '=');
            $query -> orderBy('title');
            $records = $query -> execute();
            
            foreach ($records AS $record) {
              $options[$record -> title] = $record -> title;
            }
          }
          else {
            $query = db_select('node', 'n');
            $query -> join('field_data_' . $field_val[0], 'm', 'n.nid = m.entity_id');
            $query -> fields('n', array('nid', 'title'));
            $query -> fields('m', array($field_val[0] . '_value'));
            $query -> condition('n.type', $n_type, '=');
            $query -> orderBy('title');
            $records = $query -> execute();
            
            $options = array();
            foreach ($records AS $record) {
              $record_arr = (array)$record;
              
              if ($record_arr[$field_val[0] . '_value'] != FALSE) {
                //if field VALUE is email
                if ($field_val[2]) {
                  $options[$record_arr['nid']] = $record_arr['title'];
                }
                else {
                  $options[$record_arr[$field_val[0] . '_value']] = $record_arr['title'];
                }
              }
            }
          }
          
          $form['submitted'][$input['#webform_component']['form_key']]['#type'] = 'select';
          $form['submitted'][$input['#webform_component']['form_key']]['#options'] = $options;
        }
      }
    }
  }
  
  $form['#validate'][] = 'wfso_client_form_validation';
}

function wfso_client_form_validation(&$form, &$form_state) {
  foreach ($form_state['webform']['component_tree']['children'] AS $k => $component) {
    if ($component['type'] == 'wfso_field' || $component['type'] == 'textfield') {
      
      $n_type = db_select('webform_select_opts_component', 's')
        -> fields('s', array('data'))
        -> condition('nid', $component['nid'])
        -> condition('cid', $component['cid'])
        -> execute() -> fetchField();
  
      if ($n_type) {
        $field_val = unserialize(variable_get('webform_select_options_fields_' . $n_type, ''));
      }
      
      if (isset($field_val) && $field_val[2]) {
        $value_email = db_select('field_data_' . $field_val[0], 'e')
          -> fields('e', array($field_val[0] . '_value'))
          -> condition('entity_id', @$form_state['values']['submitted'][$component['form_key']])
          -> execute() -> fetchField();
        
        $value_title = db_select('node', 'n')
          -> fields('n', array('title'))
          -> condition('nid', @$form_state['values']['submitted'][$component['form_key']])
          -> execute() -> fetchField();
        
        $form_state['values']['submitted'][$component['form_key']] = $value_email;
        
        //add node title to webform title - result in sent mail as subject
        $form_state['build_info']['args'][0] -> title = $form_state['build_info']['args'][0] -> title . ' - ' . $value_title;
      }
    }
  }
}

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * webform_component_edit_form
 */
function webform_select_opts_form_webform_component_edit_form_alter(&$form, &$form_state, $form_id) {
  
  if ($form['type']['#value'] == 'wfso_field' || $form['type']['#value'] == 'textfield') {
    $node_types = node_type_get_types();
    $options = array(0 => t('None'));
    
    foreach ($node_types AS $n_type) {
      if (variable_get('webform_select_options_for_' . $n_type -> type, 0)) {
        $options[$n_type -> type] = $n_type -> name;
      }
    }
    
    $n_type = db_select('webform_select_opts_component', 's')
      -> fields('s', array('data'))
      -> condition('nid', $form['nid']['#value'])
      -> condition('cid', $form['cid']['#value'])
      -> execute() -> fetchField();
    
    $form['webform_select_opts'] = array(
      '#type' => 'fieldset',
      '#title' => t('Select options'),
      '#collapsible' => TRUE,
      '#collapsed' => FALSE,
      '#weight' => 49,
    );
    
    $form['webform_select_opts']['wfso_value'] = array(
      '#type' => 'select',
      '#title' => t('Avalable content types'),
      '#options' => $options,
      '#default_value' => $n_type ? $n_type : 0,
    );
    
    $form['#submit'][] = 'wfso_component_save';
  }
}

function wfso_component_save($form, &$form_state) {
  db_merge('webform_select_opts_component')
    -> key(array('nid' => $form_state['values']['nid'], 'cid' => $form_state['values']['cid']))
    -> fields(array(
      'data' => $form_state['values']['webform_select_opts']['wfso_value'],
    ))
    ->execute();
}

// component code
/**
 * Implements hook_webform_component_info().
 */
function webform_select_opts_webform_component_info() {
  $components = array();

  $components['wfso_field'] = array(
    'label' => t('WF select opts field'),
    'description' => t('Webform select options module field.'),
    'features' => array(
      'csv' => TRUE,
      'default_value' => TRUE,
      'description' => TRUE,
      'email' => TRUE,
      'email_address' => TRUE,
      'email_name' => TRUE,
      'required' => TRUE,
      'title' => TRUE,
      'title_display' => TRUE,
      'title_inline' => TRUE,
      'conditional' => TRUE,
      'group' => TRUE,
      'spam_analysis' => TRUE,
      'attachment' => FALSE,
    ),
  );

  return $components;
}

function _webform_defaults_wfso_field() {
  return array(
    'name' => '',
    'form_key' => NULL,
    'pid' => 0,
    'weight' => 0,
    'value' => '',
    'mandatory' => 0,
    'extra' => array(
      'field_prefix' => '',
      'field_suffix' => '',
    ),
  );
}

/**
 * Implements _webform_theme_component().
 */
function _webform_theme_wfso_field() {
  return array(
    'webform_display_wfso_field' => array(
      'render element' => 'element',
    ),
  );
}

/**
 * Format the text output for this component.
 */
function theme_webform_display_wfso_field($variables) {
  
  $element = $variables['element'];
  $component = $element['#webform_component'];

  $options = array();
  if (is_array(@$element['#options'])) {
    foreach (@$element['#options'] as $key => $value) {
      if (is_array($value)) {
        foreach ($value as $subkey => $subvalue) {
          $options[$subkey] = $subvalue;
        }
      }
      else {
        $options[$key] = $value;
      }
    }
  }

  $items = array();
  if (@$component['extra']['multiple']) {
    foreach ((array) $element['#value'] as $option_value) {
      if ($option_value !== '') {
        // Administer provided values.
        if (isset($options[$option_value])) {
          $items[] = $options[$option_value];
        }
        // User-specified in the "other" field.
        else {
          $items[] = $option_value;
        }
      }
    }
  }
  else {
    if (isset($element['#value'][0]) && $element['#value'][0] !== '') {
      // Administer provided values.
      if (isset($options[$element['#value'][0]])) {
        $items[] = $options[$element['#value'][0]];
      }
      // User-specified in the "other" field.
      else {
        $items[] = $element['#value'][0];
      }
    }
  }

  if ($element['#format'] == 'html') {
    $output = count($items) > 1 ? theme('item_list', array('items' => $items)) : (isset($items[0]) ? $items[0] : ' ');
  }
  else {
    if (count($items) > 1) {
      foreach ($items as $key => $item) {
        $items[$key] = ' - ' . $item;
      }
      $output = implode("\n", $items);
    }
    else {
      $output = isset($items[0]) ? $items[0] : ' ';
    }
  }

  return $output;
}

function _webform_render_wfso_field($component, $value = NULL, $filter = FALSE) {
  global $user;
  $default = 0;
  
  //add default nid (of field) in url $_GET
  if (isset($_GET['default']) && is_numeric($_GET['default'])) {
    $default = $_GET['default'];
  }
  
  $options = _wfso_options($component['nid'], $component['cid'], $default);
  
  $node = isset($component['nid']) ? node_load($component['nid']) : NULL;

  $element = array(
    '#type' => 'select',
    '#title' => $filter ? _webform_filter_xss($component['name']) : $component['name'],
    '#options' => $options,
    '#default_value' => $default,
    '#required' => $component['mandatory'],
    '#weight' => $component['weight'],
    '#attributes' => @$component['extra']['attributes'],
    '#translatable' => array('title', 'description'),
    '#disabled' => $default ? TRUE : FALSE,
  );

  // Add an e-mail class for identifying the difference from normal textfields.
  @$element['#attributes']['class'][] = 'wfso_field';

  // Enforce uniqueness.
  if (@$component['extra']['unique']) {
    $element['#element_validate'][] = 'webform_validate_unique';
  }

  if (isset($value)) {
    $element['#default_value'] = $value[0];
  }

  if (@$component['extra']['disabled']) {
    if ($filter) {
      $element['#attributes']['readonly'] = 'readonly';
    }
    else {
      $element['#disabled'] = TRUE;
    }
  }

  // Change the 'width' option to the correct 'size' option.
  if (@$component['extra']['width'] > 0) {
    $element['#size'] = $component['extra']['width'];
  }

  return $element;
}

/**
 * Implements _webform_display_component().
 */
function _webform_display_wfso_field($component, $value, $format = 'html') {
  return array(
    '#title' => $component['name'],
    '#weight' => $component['weight'],
    '#theme' => 'webform_display_wfso_field',
    //'#theme_wrappers' => $format == 'html' ? array('webform_element') : array('webform_element_text'),
    '#format' => $format,
    '#value' => isset($value[0]) ? $value[0] : '',
    '#translatable' => array('title'),
  );
}

/*get options*/
function _wfso_options($nid, $cid, $default = 0) {
  global $language;
  
  $n_type = db_select('webform_select_opts_component', 's')
    -> fields('s', array('data'))
    -> condition('nid', $nid, '=')
    -> condition('cid', $cid, '=')
    -> execute() -> fetchField();
  
  if ($n_type) {
    $var = variable_get('webform_select_options_fields_' . $n_type, '');
    $field_val = unserialize($var);
    
    if ($var) {
      if ($field_val[0] == 'node_title') {
        $query = db_select('node', 'n');
        $query -> fields('n', array('nid', 'title'));
        $query -> condition('n.type', $n_type, '=');
        $query -> condition('n.status', 1, '=');
        $query -> condition('n.language', $language -> language, '=');
        $query -> orderBy('title');
        $records = $query -> execute();
        
        foreach ($records AS $record) {
          $options[$record -> title] = $record -> title;
        }
      }
      else {
        $query = db_select('node', 'n');
        $query -> join('field_data_' . $field_val[0], 'm', 'n.nid = m.entity_id');
        $query -> fields('n', array('nid', 'title'));
        $query -> fields('m', array($field_val[0] . '_value'));
        $query -> condition('n.type', $n_type, '=');
        $query -> condition('n.status', 1, '=');
        $query -> condition('n.language', $language -> language, '=');
        $query -> orderBy('title');
        $records = $query -> execute();
        
        $options = array();
        foreach ($records AS $record) {
          $record_arr = (array)$record;
          
          if ($record_arr[$field_val[0] . '_value'] != FALSE) {
            //if field VALUE is email
            if ($field_val[2]) {
              $options[$record_arr['nid']] = $record_arr['title'];
            }
            else {
              $options[$record_arr[$field_val[0] . '_value']] = $record_arr['title'];
            }
          }
        }
      }
    }
  }
  
  return $options;
}
// end component code
