You are here

civicrm_entity_price_set_field.module in CiviCRM Entity 7.2

File

modules/civicrm_entity_price_set_field/civicrm_entity_price_set_field.module
View source
<?php

/**
 * @file
 * Provide CiviCRM Entity Price Set Field Type.
 */
module_load_include('inc', 'civicrm_entity_price_set_field', 'includes/civicrm_entity_price_set_field.event_registration');
module_load_include('inc', 'civicrm_entity_price_set_field', 'includes/civicrm_entity_price_set_field.transaction');
module_load_include('inc', 'civicrm_entity_price_set_field', 'includes/civicrm_entity_price_set_field.price_set');
module_load_include('inc', 'civicrm_entity_price_set_field', 'includes/civicrm_entity_price_set_field.confirmation_page');
module_load_include('inc', 'civicrm_entity_price_set_field', 'includes/civicrm_entity_price_set_field.thank_you_page');

/**
 * Implements hook_field_info().
 *
 * @return array
 */
function civicrm_entity_price_set_field_field_info() {
  return array(
    'civicrm_entity_price_set_field' => array(
      'label' => t('CiviCRM Entity Price Set'),
      'description' => t('This field provides a widget for manipulating event and contribution page price sets.'),
      'settings' => array(
        'groups' => array(),
      ),
      'instance_settings' => array(),
      'default_widget' => 'civicrm_entity_price_set_field_default_widget',
      'default_formatter' => 'civicrm_entity_price_set_field_default_formatter',
    ),
  );
}

/**
 * Implementation of hook_rules_event_info()
 */
function civicrm_entity_price_set_field_rules_event_info() {
  return array(
    'civicrm_entity_price_set_field_event_registration' => array(
      'label' => t('Event Registration'),
      'module' => 'civicrm_entity_price_set_field',
      'group' => 'CiviCRM Entity Price Set Field',
      'variables' => array(
        'event' => array(
          'type' => 'civicrm_event',
          'label' => t('The event being registered for.'),
        ),
        'contacts' => array(
          'type' => 'list<civicrm_contact>',
          'label' => t('Contacts'),
        ),
        'participants' => array(
          'type' => 'list<civicrm_participant>',
          'label' => t('Participants'),
        ),
      ),
    ),
    'civicrm_entity_price_set_field_successful_cc_transaction' => array(
      'label' => t('Successful CC Transaction'),
      'module' => 'civicrm_entity_price_set_field',
      'group' => 'CiviCRM Entity Price Set Field',
      'variables' => array(
        'contribution' => array(
          'type' => 'civicrm_contribution',
          'label' => t('The contribution that was transacted.'),
        ),
      ),
    ),
  );
}

/**
 * Implements hook_rules_action_info()
 * Add a Rules Action for subscribing a user to a node.
 */
function civicrm_entity_price_set_field_rules_action_info() {
  return array(
    'civicrm_entity_price_set_field_send_contribution_receipt' => array(
      'label' => t('Send Contribution API sendconfirmation'),
      'group' => t('CiviCRM Entity Price Set Field'),
      'parameter' => array(
        'contribution_id' => array(
          'type' => 'integer',
          'label' => 'Contribution ID',
        ),
        'from' => array(
          'type' => 'text',
          'label' => 'From Address',
        ),
      ),
    ),
  );
}

/**
 * Sends confirmation email for a Contribution using CiviCRM API sendconfirmation action
 *
 * @param $contribution_id
 * @param $from_address
 */
function civicrm_entity_price_set_field_send_contribution_receipt($contribution_id, $from_address) {
  if (!civicrm_initialize()) {
    return;
  }
  if (!empty($contribution_id) && $contribution_id > 0 && $from_address != '') {
    try {
      $result = civicrm_api3('Contribution', 'sendconfirmation', array(
        'sequential' => 1,
        'id' => $contribution_id,
        'receipt_from_email' => $from_address,
      ));
    } catch (CiviCRM_API3_Exception $e) {
      watchdog('civicrm_entity_price_set_field', 'Contribution Receipt sending failed');
    }
  }
  else {
    watchdog('civicrm_entity_price_set_field', 'Invalid values for provided parameters.');
  }
}

/**
 * Implements hook_form_FORMID_alter().
 *
 * form id : field_ui_field_edit_form
 *
 * Alter Field Settings form to set cardinality to 1 and disable the select widget
 *
 * @param $form
 * @param $form_state
 */
function civicrm_entity_price_set_field_form_field_ui_field_edit_form_alter(&$form, &$form_state) {
  if ($form['#field']['type'] == 'civicrm_entity_price_set_field') {

    // field settings mods
    $form['field']['cardinality']['#default_value'] = 1;
    $form['field']['cardinality']['#disabled'] = TRUE;
  }
}

/**
 * Implements hook_form_FORMID_alter().
 *
 * form id : field_ui_field_overview_form
 *
 * Only allow creation of civicrm_entity_price_set_field to civicrm_event or civicrm_contribution_page entity type
 *
 * @param $form
 * @param $form_state
 */
function civicrm_entity_price_set_field_form_field_ui_field_overview_form_alter(&$form, &$form_state) {
  if ($form['#entity_type'] != 'civicrm_event' && $form['#entity_type'] != 'civicrm_contribution_page') {
    unset($form['fields']['_add_new_field']['type']['#options']['civicrm_entity_price_set_field']);
    foreach ($form['fields']['_add_existing_field']['field_name']['#options'] as $field_name => $description) {
      if (strpos($description, 'CiviCRM Entity Price Set') !== FALSE) {
        unset($form['fields']['_add_existing_field']['field_name']['#options'][$field_name]);
      }
    }
  }
}

/**
 * Implements hook_field_settings_form().
 *
 * @param $field
 * @param $instance
 * @param $has_data
 */
function civicrm_entity_price_set_field_field_settings_form($field, $instance, $has_data) {
  $defaults = field_info_field_settings($field['type']);
  $settings = array_merge($defaults, $field['settings']);

  // $options = array('civicrm_contribution_page' => 'Contribution Page', 'civicrm_event' => 'Event');

  /*$form['price_set_entity_table'] = array(
      '#type' => 'select',
      '#title' => t('Price Set Entity Table'),
      '#multiple' => TRUE,
      '#default_value' => $settings['price_set_entity_table'],
      '#description' => t('Entity table for the price set field'),
      '#options' => $options,
    )*/

  //return $form;
}

/**
 * Implements hook_field_widget_info_alter().
 *
 * @param $info
 */
function civicrm_entity_price_set_field_field_widget_info_alter(&$info) {
  $info['inline_entity_form']['field types'][] = 'civicrm_entity_price_set_field';
  $info['inline_entity_form_single']['field types'][] = 'civicrm_entity_price_set_field';
}

/**
 * Implements hook_inline_entity_form_settings_alter().
 *
 * @param $settings
 * @param $field
 * @param $instance
 */
function civicrm_entity_price_set_field_inline_entity_form_settings_alter(&$settings, $field, $instance) {
  if ($field['type'] == 'civicrm_entity_price_set_field') {
    $settings['entity_type'] = 'civicrm_price_set';
    $settings['column'] = 'price_set_id';
    $settings['bundles'] = array(
      'civicrm_price_set',
    );
  }
}

/**
 * Implements hook_field_load().
 *
 * @param $entity_type
 * @param $entities
 * @param $field
 * @param $instances
 * @param $langcode
 * @param $items
 * @param $age
 */
function civicrm_entity_price_set_field_field_load($entity_type, $entities, $field, $instances, $langcode, &$items, $age) {
  if ($entity_type == 'civicrm_event' || $entity_type == 'civicrm_contribution_page') {
    foreach ($entities as $entity_id => $entity) {
      $query = db_select('civicrm_price_set_entity', 'pce');
      $price_set_id = $query
        ->fields('pce', array(
        'price_set_id',
      ))
        ->condition('entity_table', $entity_type)
        ->condition('entity_id', $entity_id)
        ->execute()
        ->fetchField();
      if (!empty($price_set_id)) {
        $items[$entity_id][0]['price_set_id'] = $price_set_id;
      }
      else {
        $items[$entity_id][0]['price_set_id'] = 0;
      }
    }
  }
}

/**
 * Implements hook_field_is_empty().
 *
 * @param $item
 * @param $field
 * @return bool
 */
function civicrm_entity_price_set_field_field_is_empty($item, $field) {
  if (isset($item['price_set_id']) && !is_numeric($item['price_set_id']) || empty($item['price_set_id'])) {
    return TRUE;
  }
  return FALSE;
}

/**
 * Implements hook_field_insert().
 *
 * @param $entity_type
 * @param $entity
 * @param $field
 * @param $instance
 * @param $langcode
 * @param $items
 */
function civicrm_entity_price_set_field_field_insert($entity_type, $entity, $field, $instance, $langcode, &$items) {
  if ($entity_type == 'civicrm_event') {
    if (empty($items[0]['price_set_id']) && !is_numeric($items[0]['price_set_id'])) {
      return;
    }
    else {
      if (!empty($entity->id)) {
        _civicrm_entity_price_set_field_process_field_items($entity_type, $entity->id, $field, $instance, $items);
      }
    }
  }
}

/**
 * Implements hook_field_update().
 *
 * @param $entity_type
 * @param $entity
 * @param $field
 * @param $instance
 * @param $langcode
 * @param $items
 */
function civicrm_entity_price_set_field_field_update($entity_type, $entity, $field, $instance, $langcode, &$items) {
  if ($entity_type == 'civicrm_event') {
    if (empty($items[0]['price_set_id']) && !is_numeric($items[0]['price_set_id'])) {
      return;
    }
    else {
      if (!empty($entity->id)) {
        _civicrm_entity_price_set_field_process_field_items($entity_type, $entity->id, $field, $instance, $items);
      }
    }
  }
}

/**
 * Helper function to process field items on entity update
 *
 * @param $entity_type
 * @param $entity_id
 * @param $field
 * @param $instance
 * @param $items
 */
function _civicrm_entity_price_set_field_process_field_items($entity_type, $entity_id, $field, $instance, &$items) {

  // maybe the different widgets need different stuff
  if ($instance['widget']['type'] == 'civicrm_entity_price_set_field_simple_widget' && civicrm_initialize()) {

    // first check if there is only one empty row, if so then don't do anything
    // if there are more than one row, at least more than one with some values, then start the process
    $abort = TRUE;
    if (count($items[0]['price_set']['price_field'])) {
      foreach ($items[0]['price_set']['price_field'] as $id => $values) {
        if (!empty($values['label']) && !empty($values['amount'])) {
          $abort = FALSE;
        }
        else {
          unset($items[0]['price_set']['price_field'][$id]);
        }
      }
    }
    if ($abort) {
      return;
    }

    //fetch event by api to use its values....
    try {
      $result = civicrm_api3(substr($entity_type, 8), 'get', array(
        'id' => $entity_id,
        'sequential' => 1,
      ));
    } catch (CiviCRM_API3_Exception $e) {
      drupal_set_message('Error fetching event when attempting to save price set');
      return;
    }
    if ($result['count']) {
      $event = $result['values'][0];
    }
    else {
      drupal_set_message('Error fetching event when attempting to save price set');
      return;
    }

    //if price_set_id = 0;
    if ($items[0]['price_set_id'] == 0) {

      //create price set and update item data structure
      $items[0]['price_set']['orig_data']['price_set']->title = $event['title'];
      $items[0]['price_set']['orig_data']['price_set']->is_active = 1;
      $items[0]['price_set']['orig_data']['price_set']->is_quick_config = 1;
      switch ($entity_type) {
        case 'civicrm_event':
          $items[0]['price_set']['orig_data']['price_set']->extends = 'CiviEvent';
          break;
      }
      if (!empty($event['financial_type_id'])) {
        $items[0]['price_set']['orig_data']['price_set']->financial_type_id = $event['financial_type_id'];
      }
      $price_set_wrapper = entity_metadata_wrapper('civicrm_price_set', $items[0]['price_set']['orig_data']['price_set']);
      try {
        $price_set_wrapper
          ->save();
      } catch (Exception $e) {
        drupal_set_message('Error creating price set.');
        watchdog_exception('civicrm_entity_price_set_field', $e);
        return;
      }
      $items[0]['price_set_id'] = $price_set_wrapper->id
        ->value();

      // create price set entity
      db_insert('civicrm_price_set_entity')
        ->fields(array(
        'entity_table' => $entity_type,
        'entity_id' => $event['id'],
        'price_set_id' => $items[0]['price_set_id'],
      ))
        ->execute();

      //create price field and update item data structure
      $items[0]['price_set']['orig_data']['price_fields'][0]['pf_entity']->label = $event['fee_label'];
      $items[0]['price_set']['orig_data']['price_fields'][0]['pf_entity']->html_type = 'Radio';
      $items[0]['price_set']['orig_data']['price_fields'][0]['pf_entity']->weight = 1;
      $items[0]['price_set']['orig_data']['price_fields'][0]['pf_entity']->is_enter_quantity = 0;
      $items[0]['price_set']['orig_data']['price_fields'][0]['pf_entity']->is_display_amounts = 1;
      $items[0]['price_set']['orig_data']['price_fields'][0]['pf_entity']->options_per_line = 1;
      $items[0]['price_set']['orig_data']['price_fields'][0]['pf_entity']->is_active = 1;
      $items[0]['price_set']['orig_data']['price_fields'][0]['pf_entity']->is_required = 1;
      $items[0]['price_set']['orig_data']['price_fields'][0]['pf_entity']->visibility_id = 1;
      $items[0]['price_set']['orig_data']['price_fields'][0]['pf_entity']->price_set_id = $items[0]['price_set_id'];
      $price_field_wrapper = entity_metadata_wrapper('civicrm_price_field', $items[0]['price_set']['orig_data']['price_fields'][0]['pf_entity']);
      try {
        $price_field_wrapper
          ->save();
      } catch (Exception $e) {
        drupal_set_message('Error creating price field.');
        watchdog_exception('civicrm_entity_price_set_field', $e);
        return;
      }
      $price_field_id = $items[0]['price_set']['orig_data']['price_fields'][0]['price_field_id'] = $price_field_wrapper->id
        ->value();
      $temp_pf = $items[0]['price_set']['orig_data']['price_fields'][0];
      unset($items[0]['price_set']['orig_data']['price_fields'][0]);
      $items[0]['price_set']['orig_data']['price_fields'][$price_field_id] = $temp_pf;
    }
    $price_field_ids = array_keys($items[0]['price_set']['orig_data']['price_fields']);
    $price_field_id = $price_field_ids[0];
    foreach ($items[0]['price_set']['price_field'] as $id => $values) {
      if (empty($values['label']) && empty($values['amount']) && empty($values['is_default'])) {
        continue;
      }

      // if new get data and add some defaults
      if (strpos($id, 'new-') === 0) {

        //need the financial type id of the event
        $price_field_value = new CiviCRMEntity(array(
          'is_new' => TRUE,
          'price_field_id' => $price_field_id,
          'name' => strtolower($values['label']),
          'label' => $values['label'],
          'amount' => $values['amount'],
          'weight' => $values['weight'],
          'is_default' => $values['is_default'],
          'is_active' => 1,
        ), 'civicrm_price_field_value');
        if (!empty($event['financial_type_id'])) {
          $price_field_value->financial_type_id = $event['financial_type_id'];
        }
        $wrapper = entity_metadata_wrapper('civicrm_price_field_value', $price_field_value);
      }
      else {

        // else update existing values
        $items[0]['price_set']['orig_data']['price_fields'][$price_field_id]['price_field_values'][$id]->label = $values['label'];
        $items[0]['price_set']['orig_data']['price_fields'][$price_field_id]['price_field_values'][$id]->amount = $values['amount'];
        $items[0]['price_set']['orig_data']['price_fields'][$price_field_id]['price_field_values'][$id]->weight = $values['weight'];
        $items[0]['price_set']['orig_data']['price_fields'][$price_field_id]['price_field_values'][$id]->is_default = $values['is_default'];
        $wrapper = entity_metadata_wrapper('civicrm_price_field_value', $items[0]['price_set']['orig_data']['price_fields'][$price_field_id]['price_field_values'][$id]);
      }
      try {
        $wrapper
          ->save();
      } catch (Exception $e) {
        drupal_set_message('Error saving price field value.');
        watchdog_exception('civicrm_entity_price_set_field', $e);
      }
    }

    // delete necessary items
    foreach ($items[0]['price_set']['orig_data']['price_fields'][$price_field_id]['price_field_values'] as $pfv_id => $values) {
      if (is_numeric($pfv_id) && !isset($items[0]['price_set']['price_field'][$pfv_id])) {
        $wrapper = entity_metadata_wrapper('civicrm_price_field_value', $items[0]['price_set']['orig_data']['price_fields'][$price_field_id]['price_field_values'][$pfv_id]);
        try {
          $wrapper
            ->delete();
        } catch (Exception $e) {
          drupal_set_message('Error removing price field value.');
          watchdog_exception('civicrm_entity_price_set_field', $e);
        }
      }
    }
  }
}

/**
 * Utility function to load the price set and child entities relevant to the widget or display formatter
 *
 * @param $price_set_id
 * @return bool|array
 */
function _civicrm_entity_price_set_field_get_relevant_entities($price_set_id) {
  $data = array();
  $price_set = entity_load_single('civicrm_price_set', $price_set_id);
  if ($price_set) {
    $data['price_set'] = $price_set;
    $price_field_query = new EntityFieldQuery();
    $price_field_result = $price_field_query
      ->entityCondition('entity_type', 'civicrm_price_field')
      ->propertyCondition('price_set_id', $price_set_id)
      ->propertyOrderBy('weight', 'ASC')
      ->execute();
    $data['price_fields'] = array();
    if (!empty($price_field_result['civicrm_price_field'])) {
      foreach ($price_field_result['civicrm_price_field'] as $id => $pf_id) {
        $data['price_fields'][$id]['price_field_id'] = $id;
        $data['price_fields'][$id]['pf_entity'] = entity_load_single('civicrm_price_field', $id);
        $data['price_fields'][$id]['price_field_values'] = array();
        $price_field_value_query = new EntityFieldQuery();
        $price_field_value_result = $price_field_value_query
          ->entityCondition('entity_type', 'civicrm_price_field_value')
          ->propertyCondition('price_field_id', $id)
          ->propertyOrderBy('weight', 'ASC')
          ->execute();
        if (!empty($price_field_value_result['civicrm_price_field_value'])) {
          $data['price_fields'][$id]['price_field_values'] = entity_load('civicrm_price_field_value', array_keys($price_field_value_result['civicrm_price_field_value']));
        }
      }
    }
  }
  else {
    return FALSE;
  }
  return $data;
}

/**
 * Utility function to load the price set and child entities.  This method clones the entity objects so the registration form can alter the values
 *
 * @param $price_set_id
 * @return bool|array
 */
function _civicrm_entity_price_set_field_get_relevant_entities_clone($price_set_id) {
  $data = array();
  $price_set = clone entity_load_single('civicrm_price_set', $price_set_id);
  if ($price_set) {
    $data['price_set'] = $price_set;
    $price_field_query = new EntityFieldQuery();
    $price_field_result = $price_field_query
      ->entityCondition('entity_type', 'civicrm_price_field')
      ->propertyCondition('price_set_id', $price_set_id)
      ->propertyOrderBy('weight', 'ASC')
      ->execute();
    $data['price_fields'] = array();
    if (!empty($price_field_result['civicrm_price_field'])) {
      foreach ($price_field_result['civicrm_price_field'] as $id => $pf_id) {
        $data['price_fields'][$id]['price_field_id'] = $id;
        $data['price_fields'][$id]['pf_entity'] = clone entity_load_single('civicrm_price_field', $id);
        $data['price_fields'][$id]['price_field_values'] = array();
        $price_field_value_query = new EntityFieldQuery();
        $price_field_value_result = $price_field_value_query
          ->entityCondition('entity_type', 'civicrm_price_field_value')
          ->propertyCondition('price_field_id', $id)
          ->propertyOrderBy('weight', 'ASC')
          ->execute();
        if (!empty($price_field_value_result['civicrm_price_field_value'])) {
          foreach ($price_field_value_result['civicrm_price_field_value'] as $id2 => $pfv_id) {
            $data['price_fields'][$id]['price_field_values'][$id2] = clone entity_load_single('civicrm_price_field_value', $id2);
          }
        }
      }
    }
  }
  else {
    return FALSE;
  }
  return $data;
}

/**
 * Helper function to setup data structure for price set, price field, price field values, for an event
 *
 * @return array
 */
function _civicrm_entity_price_set_field_setup_entities() {
  $data = array();
  $data['price_set'] = new CiviCRMEntity(array(
    'is_new' => TRUE,
  ), 'civicrm_price_set');
  $data['price_fields'][0]['price_field_id'] = 0;
  $data['price_fields'][0]['pf_entity'] = new CiviCRMEntity(array(
    'is_new' => TRUE,
  ), 'civicrm_price_field');
  $data['price_fields'][0]['price_field_values']['new-0'] = new CiviCRMEntity(array(
    'is_new' => TRUE,
    'label' => '',
    'amount' => '',
    'weight' => 0,
    'is_default' => 0,
  ), 'civicrm_price_field_value');
  return $data;
}

/**
 *
 *
 * Field Widget -- Simple
 *
 *
 */

/**
 * Implements hook_field_widget_info().
 */
function civicrm_entity_price_set_field_field_widget_info() {
  return array(
    'civicrm_entity_price_set_field_simple_widget' => array(
      'label' => t('Simple -- one price field'),
      'field types' => array(
        'civicrm_entity_price_set_field',
      ),
      'settings' => array(),
      'behaviors' => array(
        'multiple values' => FIELD_BEHAVIOR_DEFAULT,
        'default value' => FIELD_BEHAVIOR_DEFAULT,
      ),
    ),
  );
}

/**
 * Implements hook_field_widget_form().
 */
function civicrm_entity_price_set_field_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
  $orig_element = $element;
  switch ($instance['widget']['type']) {
    case 'civicrm_entity_price_set_field_simple_widget':
      if (!empty($items[$delta]['price_set_id'])) {
        $price_set_id = $items[$delta]['price_set_id'];
      }
      else {
        $price_set_id = 0;
      }
      $entity_type = $instance['entity_type'];
      $widget = $orig_element + array(
        '#type' => 'value',
        '#value' => $price_set_id,
      );
      $element['price_set_id'] = $widget;
      _civicrm_entity_price_set_field_prepare_simple_widget($price_set_id, $instance, $element);
      drupal_add_js(drupal_get_path('module', 'civicrm_entity_price_set_field') . '/js/civicrm_entity_price_set_field_simple_widget.js');
      break;
    case 'civicrm_entity_price_set_field_full_edit_widget':

      // To Be Developed -- this widget should have the works, multiple price fields, editing of price set settings, price field settings etc...
      if (!empty($items[$delta]['price_set_id'])) {
        $price_set_id = $items[$delta]['price_set_id'];
      }
      else {
        $price_set_id = 0;
      }
      $data = _civicrm_entity_price_set_field_get_relevant_entities($price_set_id);
      $widget = $orig_element + array(
        '#type' => 'value',
        '#value' => !empty($items[$delta]['price_set_id']) ? $items[$delta]['price_set_id'] : NULL,
      );
      $element['price_set_id'] = $widget;
      break;
  }
  return $element;
}

/**
 * Helper function to create FAPI form element for the Simple widget
 *
 * @param $price_set_id
 * @param $instance
 * @param $element
 */
function _civicrm_entity_price_set_field_prepare_simple_widget($price_set_id, $instance, &$element) {
  $entity_type = $instance['entity_type'];
  switch ($entity_type) {
    case 'civicrm_event':
      break;
  }

  // setup price set form elements
  $element['price_set'] = array(
    '#type' => 'fieldset',
    '#title' => t($instance['label']),
    '#collapsible' => TRUE,
    '#collapsed' => FALSE,
  );
}

/**
 *  Implements hook_field_widget_form_alter().
 *
 * We have to implement to gain access to the form state, for ajax
 *
 * @param $element
 * @param $form_state
 * @param $context
 */
function civicrm_entity_price_set_field_field_widget_form_alter(&$element, &$form_state, $context) {
  if ($context['instance']['widget']['type'] == 'civicrm_entity_price_set_field_simple_widget') {
    $element['#attached']['css'][] = drupal_get_path('module', 'civicrm_entity_price_set_field') . '/css/simple_widget.css';
    $price_set_id = $element['price_set_id']['#value'];

    // need these form state checks because of all the ajax
    // setup, or reuse the data
    if (empty($form_state['price_set_data'])) {
      if ($price_set_id) {
        $data = _civicrm_entity_price_set_field_get_relevant_entities($price_set_id);
      }
      else {
        $data = _civicrm_entity_price_set_field_setup_entities();
      }
      $form_state['price_set_data'] = $data;
    }
    else {
      $data = $form_state['price_set_data'];
    }
    $element['price_set']['orig_data'] = array(
      '#type' => 'value',
      '#value' => $data,
    );

    // setup price field form elements
    $data = $element['price_set']['orig_data']['#value'];
    $price_field = reset($data['price_fields']);
    $element['price_set']['price_field'] = array(
      '#prefix' => '<div id="price-field-' . $price_field['price_field_id'] . '-attributes">',
      '#suffix' => '</div>',
      '#tree' => TRUE,
      '#theme' => 'civicrm_entity_price_set_field_price_field_drag_components',
    );
    if (empty($form_state['price_field_values-' . $price_field['price_field_id']])) {
      if (!empty($price_field['price_field_values'])) {
        foreach ($price_field['price_field_values'] as $id => $price_field_value) {
          $form_state['price_field_values-' . $price_field['price_field_id']][$id] = $price_field_value;
        }
      }
    }
    if (!isset($form_state['num_new_rows'])) {
      $form_state['num_new_rows'] = 0;
    }

    // setup price field value form elements
    if (!empty($form_state['price_field_values-' . $price_field['price_field_id']])) {
      foreach ($form_state['price_field_values-' . $price_field['price_field_id']] as $id => $price_field_value) {
        $element['price_set']['price_field'][$id]['weight'] = array(
          '#type' => 'textfield',
          '#default_value' => $price_field_value->weight,
          '#attributes' => array(
            'class' => array(
              'item-row-weight',
            ),
          ),
        );
        $element['price_set']['price_field'][$id]['label'] = array(
          '#element_id' => $id,
          '#type' => 'textfield',
          '#title' => 'Label',
          '#default_value' => $price_field_value->label,
          '#element_validate' => array(
            '_civicrm_entity_price_set_field_label_element_validate',
          ),
        );
        $element['price_set']['price_field'][$id]['amount'] = array(
          '#element_id' => $id,
          '#type' => 'textfield',
          '#title' => 'Amount',
          '#default_value' => $price_field_value->amount,
          '#element_validate' => array(
            '_civicrm_entity_price_set_field_amount_element_validate',
          ),
        );
        $element['price_set']['price_field'][$id]['is_default'] = array(
          '#type' => 'radio',
          '#title' => '',
          '#return_value' => 1,
          '#default_value' => $price_field_value->is_default,
        );
        $element['price_set']['price_field'][$id]['remove_row'] = array(
          '#element_id' => $id,
          '#price_field_id' => $price_field['price_field_id'],
          '#type' => 'submit',
          '#value' => 'Remove',
          '#name' => 'remove-button-' . $id,
          '#submit' => array(
            '_civicrm_entity_price_set_field_simple_widget_remove_button_submit',
          ),
          '#limit_validation_errors' => array(
            array(
              'price_field',
              $id,
            ),
          ),
          '#ajax' => array(
            'callback' => '_civicrm_entity_price_set_field_simple_widget_price_field_ajax',
            'wrapper' => 'price-field-' . $price_field['price_field_id'] . '-attributes',
            'method' => 'replace',
            'effect' => 'fade',
          ),
        );
      }
    }

    //Add Option button
    $element['price_set']['price_field' . $price_field['price_field_id']]['add_row'] = array(
      '#price_field_id' => $price_field['price_field_id'],
      '#type' => 'submit',
      '#value' => 'Add Option',
      '#name' => 'add-option-button',
      '#submit' => array(
        '_civicrm_entity_price_set_field_simple_widget_add_button_submit',
      ),
      '#limit_validation_errors' => array(
        array(
          'price_field',
          'price_field' . $price_field['price_field_id'],
        ),
      ),
      '#ajax' => array(
        'callback' => '_civicrm_entity_price_set_field_simple_widget_price_field_ajax',
        'wrapper' => 'price-field-' . $price_field['price_field_id'] . '-attributes',
        'method' => 'replace',
        'effect' => 'fade',
      ),
    );
  }
}

/**
 * Helper function to setup the price set data area for a new entity
 *
 * @param $entity_type
 * @return array
 */
function _civicrm_entity_price_set_field_create_new_priceset_data($entity_type) {
  $data = array();
  switch ($entity_type) {
    case 'civicrm_event':
      break;
  }
  return $data;
}

/**
 * Implements hook_theme().
 */
function civicrm_entity_price_set_field_theme($existing, $type, $theme, $path) {
  $themes = array(
    'civicrm_entity_price_set_field_price_field_drag_components' => array(
      'render element' => 'element',
    ),
    'civicrm_entity_price_set_field_price_field_display_form_confirmation_page' => array(
      'render element' => 'element',
      'variables' => array(
        'form_data' => NULL,
        'entity_type',
        'entity' => NULL,
        'price_set_data' => NULL,
        'heading' => 'Confirmation Page',
      ),
    ),
    'civicrm_entity_price_set_field_price_field_display_form_thank_you_page' => array(
      'render element' => 'element',
      'variables' => array(
        'form_data' => NULL,
        'entity_type',
        'entity' => NULL,
        'price_set_data' => NULL,
        'heading' => 'Thank You Page',
      ),
    ),
  );
  return $themes;
}

/**
 * Theme function for price field form components
 *
 * @param $vars
 * @return string|void
 */
function theme_civicrm_entity_price_set_field_price_field_drag_components($vars) {
  $element = $vars['element'];
  drupal_add_tabledrag('price_field_value_table', 'order', 'sibling', 'item-row-weight');
  $header = array(
    '' => '',
    'weight' => t('Weight'),
    'label' => t('Label'),
    'amount' => t('Amount'),
    'is_default' => t('Default'),
    'remove_row' => t('Delete'),
  );
  $rows = array();
  foreach (element_children($element) as $key) {
    $row = array();
    $row['data'] = array();
    foreach ($header as $fieldname => $title) {
      $row['data'][] = drupal_render($element[$key][$fieldname]);
      $row['class'] = array(
        'draggable',
      );
    }
    $rows[] = $row;
  }
  return theme('table', array(
    'header' => $header,
    'rows' => $rows,
    'attributes' => array(
      'id' => 'price_field_value_table',
    ),
  ));
}

/**
 * Submit callback for Price Field Values table Remove button , Simple Widget
 *
 * @param $form
 * @param $form_state
 */
function _civicrm_entity_price_set_field_simple_widget_remove_button_submit($form, &$form_state) {
  $element_id = $form_state['triggering_element']['#element_id'];
  $price_field_id = $form_state['triggering_element']['#price_field_id'];
  unset($form_state['price_field_values-' . $price_field_id][$element_id]);
  $form_state['rebuild'] = TRUE;
}

/**
 * Submit callback for Price Field Values table add button, Simple Widget
 *
 * @param $form
 * @param $form_state
 */
function _civicrm_entity_price_set_field_simple_widget_add_button_submit($form, &$form_state) {
  $form_state['num_new_rows'] += 1;
  $price_field_id = $form_state['triggering_element']['#price_field_id'];
  $defaults = new stdClass();
  $defaults->label = '';
  $defaults->amount = '';
  $defaults->is_default = 0;
  $largest_weight = 0;
  foreach ($form_state['price_field_values-' . $price_field_id] as $id => $values) {
    if ($values->weight > $largest_weight) {
      $largest_weight = $values->weight;
    }
  }
  $defaults->weight = $largest_weight + 1;
  $form_state['price_field_values-' . $price_field_id]['new-' . $form_state['num_new_rows']] = $defaults;
  $form_state['rebuild'] = TRUE;
}

/**
 * Ajax callback for Price Field Values table, Simple Widget
 *
 * @param $form
 * @param $form_state
 * @return array|null
 */
function _civicrm_entity_price_set_field_simple_widget_price_field_ajax($form, $form_state) {
  $element_id = $form_state['triggering_element']['#element_id'];
  $price_field_id = $form_state['triggering_element']['#price_field_id'];
  $element_parents = $form_state['triggering_element']['#parents'];
  $parents = array();
  $field_name = '';
  foreach ($element_parents as $index => $parent) {
    if (strpos($parent, 'field_') === 0) {
      $field_name = str_replace('_', '-', $parent);
    }
    if (strpos($parent, 'price_field') === 0) {
      $parents[] = 'price_field';
      break;
    }
    else {
      $parents[] = $parent;
    }
  }
  $output = drupal_array_get_nested_value($form, $parents);
  $row_state = drupal_array_get_nested_value($form_state['input'], $parents);
  $selected_id = 0;
  foreach ($row_state as $id => $values) {
    if ($values['is_default'] == 1) {
      $selected_id = $id;
      break;
    }
  }
  $commands = array();
  $commands[] = ajax_command_html('#price-field-' . $price_field_id . '-attributes', render($output));
  $commands[] = array(
    'command' => 'afterPriceFieldAjaxReplaceCallback',
    'selectedValue' => $selected_id,
    'fieldName' => $field_name,
  );
  return array(
    '#type' => 'ajax',
    '#commands' => $commands,
  );
}

/**
 * Element validation handler for price field value label element of the price set widget
 *
 * @param $element
 * @param $form_state
 * @param $form
 */
function _civicrm_entity_price_set_field_label_element_validate($element, &$form_state, $form) {
  $element_parents = $element['#parents'];
  $element_id = $element['#element_id'];
  $parents = array();
  foreach ($element_parents as $index => $parent) {
    if (!is_numeric($parent) && $parent == 'price_field') {
      $parents[] = 'price_field';
      break;
    }
    else {
      $parents[] = $parent;
    }
  }
  $price_field_values = drupal_array_get_nested_value($form_state['values'], $parents);
  if (strpos($element_id, 'new-') !== FALSE && empty($price_field_values[$element_id]['label']) && empty($price_field_values[$element_id]['amount']) && empty($price_field_values[$element_id]['is_default'])) {

    // ignore?
  }
  else {
    if (empty($price_field_values[$element_id]['label'])) {
      form_set_error(implode('][', $parents) . '][' . $element_id . '][label', t('Label cannot be empty'));
    }
  }
}

/**
 * Element validation handler for price field value amount element of the price set widget
 *
 * @param $element
 * @param $form_state
 * @param $form
 */
function _civicrm_entity_price_set_field_amount_element_validate($element, &$form_state, $form) {
  $element_parents = $element['#parents'];
  $element_id = $element['#element_id'];
  $parents = array();
  foreach ($element_parents as $index => $parent) {
    if (!is_numeric($parent) && $parent == 'price_field') {
      $parents[] = 'price_field';
      break;
    }
    else {
      $parents[] = $parent;
    }
  }
  $price_field_values = drupal_array_get_nested_value($form_state['values'], $parents);
  if (strpos($element_id, 'new-') !== FALSE && empty($price_field_values[$element_id]['label']) && empty($price_field_values[$element_id]['amount']) && empty($price_field_values[$element_id]['is_default'])) {

    // ignore?
  }
  else {
    if (isset($price_field_values[$element_id]['amount']) && $price_field_values[$element_id]['amount'] == '') {
      form_set_error(implode('][', $parents) . '][' . $element_id . '][amount', t('Amount cannot be empty'));
    }
    elseif (!is_numeric($price_field_values[$element_id]['amount'])) {
      form_set_error(implode('][', $parents) . '][' . $element_id . '][amount', t('Amount must be numeric (do not include "$" sign)'));
    }
  }
}

/**
 *
 *
 * Field Formatter
 *
 *
 */

/**
 * Implements hook_field_formatter_info().
 */
function civicrm_entity_price_set_field_field_formatter_info() {
  return array(
    'civicrm_entity_price_set_field_form_formatter' => array(
      // Machine name of the formatter
      'label' => t('Form'),
      'field types' => array(
        'civicrm_entity_price_set_field',
      ),
      'settings' => array(
        // Array of the settings we'll create
        'test_transaction' => 0,
      ),
    ),
  );
}

/**
 * Implements hook_field_formatter_settings_form().
 *
 * @param $field
 * @param $instance
 * @param $view_mode
 * @param $form
 * @param $form_state
 * @return array
 */
function civicrm_entity_price_set_field_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
  if ($field['type'] == 'civicrm_entity_price_set_field') {
    $display = $instance['display'][$view_mode];
    $settings = $display['settings'];
    $element = array();
    $element['test_transaction'] = array(
      '#type' => 'checkbox',
      '#title' => t('Transaction test mode'),
      '#description' => 'Check box to process transactions in test mode.',
      '#return_value' => 1,
      '#default_value' => isset($settings['test_transaction']) ? $settings['test_transaction'] : 0,
    );
    return $element;
  }
}

/**
 * Implements hook_field_formatter_settings_summary().
 *
 * @param $field
 * @param $instance
 * @param $view_mode
 * @return string
 */
function civicrm_entity_price_set_field_field_formatter_settings_summary($field, $instance, $view_mode) {
  if ($field['type'] == 'civicrm_entity_price_set_field') {
    $display = $instance['display'][$view_mode];
    $settings = $display['settings'];
    $summary = '';
    if ($display['type'] == 'civicrm_entity_price_set_field_form_formatter') {
      $summary = t('CC Transactions run in @data mode', array(
        '@data' => empty($settings['test_transaction']) ? 'live' : 'test',
      ));
    }
    return $summary;
  }
}

/**
 * Implements hook_field_formatter_view().
 */
function civicrm_entity_price_set_field_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
  $element = array();
  $settings = $display['settings'];
  switch ($display['type']) {
    case 'civicrm_entity_price_set_field_form_formatter':
      foreach ($items as $delta => $item) {
        if (!empty($item['price_set_id'])) {
          $price_set_id = $item['price_set_id'];
        }
        else {
          $price_set_id = 0;
        }
        switch ($entity_type) {
          case 'civicrm_event':
            $price_set_form = drupal_get_form('civicrm_entity_price_set_field_display_form_event', $price_set_id, $entity_type, $entity, $field, $instance, $display);
            break;
        }
        $price_set_form['#form_id'] = 'civicrm_entity_price_set_display_form-' . $field['field_name'] . '-' . $langcode . '-' . $delta;
        $element[$delta] = $price_set_form;
      }
      break;
  }
  return $element;
}

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * Alter the CiviCRM Entity enabled entities settings form
 *
 * Insure necessary entity types for this module remain enabled
 *
 * @param $form
 * @param $form_state
 */
function civicrm_entity_price_set_field_form_civicrm_entity_admin_settings_form_alter(&$form, &$form_state) {
  $required_entities = array(
    'civicrm_contact' => 'Contact',
    'civicrm_contribution' => 'Contribution',
    'civicrm_event' => 'Event',
    'civicrm_line_item' => 'Line Item',
    'civicrm_participant' => 'Participant',
    'civicrm_participant_payment' => 'Participant Payment',
    'civicrm_price_set' => 'Price Set',
    'civicrm_price_field' => 'Price Field',
    'civicrm_price_field_value' => 'Price Field Value',
    'civicrm_payment_processor' => 'Payment Processor',
    'civicrm_payment_processor_type' => 'Payment Processor Type',
  );
  foreach ($required_entities as $drupal_entity_type => $entity_type_label) {
    if (empty($selected_entities[$drupal_entity_type])) {
      $form['civicrm_entity_admin_enabled_entities'][$drupal_entity_type]['#disabled'] = TRUE;
      $form['civicrm_entity_admin_enabled_entities'][$drupal_entity_type]['#default_value'] = 1;
    }
  }
  $form['#validate'][] = 'civicrm_entity_price_set_field_admin_settings_form_validate';
}

/**
 * Validation callback for the CiviCRM Entity Enabled Entities form at 'admin/structure/civicrm-entity/settings'
 *
 * @param $form
 * @param $form_state
 */
function civicrm_entity_price_set_field_admin_settings_form_validate($form, &$form_state) {
  $selected_entities = $form_state['values']['civicrm_entity_admin_enabled_entities'];
  $required_entities = array(
    'civicrm_contact' => 'Contact',
    'civicrm_contribution' => 'Contribution',
    'civicrm_event' => 'Event',
    'civicrm_line_item' => 'Line Item',
    'civicrm_participant' => 'Participant',
    'civicrm_participant_payment' => 'Participant Payment',
    'civicrm_price_set' => 'Price Set',
    'civicrm_price_field' => 'Price Field',
    'civicrm_price_field_value' => 'Price Field Value',
    'civicrm_payment_processor' => 'Payment Processor',
    'civicrm_payment_processor_type' => 'Payment Processor Type',
  );
  foreach ($required_entities as $drupal_entity_type => $entity_type_label) {
    if (empty($selected_entities[$drupal_entity_type])) {
      form_set_error('civicrm_entity_admin_enabled_entities][' . $drupal_entity_type, $entity_type_label . ' required by CiviCRM Entity Price Set Field module');
    }
  }
}

Functions

Namesort descending Description
civicrm_entity_price_set_field_admin_settings_form_validate Validation callback for the CiviCRM Entity Enabled Entities form at 'admin/structure/civicrm-entity/settings'
civicrm_entity_price_set_field_field_formatter_info Implements hook_field_formatter_info().
civicrm_entity_price_set_field_field_formatter_settings_form Implements hook_field_formatter_settings_form().
civicrm_entity_price_set_field_field_formatter_settings_summary Implements hook_field_formatter_settings_summary().
civicrm_entity_price_set_field_field_formatter_view Implements hook_field_formatter_view().
civicrm_entity_price_set_field_field_info Implements hook_field_info().
civicrm_entity_price_set_field_field_insert Implements hook_field_insert().
civicrm_entity_price_set_field_field_is_empty Implements hook_field_is_empty().
civicrm_entity_price_set_field_field_load Implements hook_field_load().
civicrm_entity_price_set_field_field_settings_form Implements hook_field_settings_form().
civicrm_entity_price_set_field_field_update Implements hook_field_update().
civicrm_entity_price_set_field_field_widget_form Implements hook_field_widget_form().
civicrm_entity_price_set_field_field_widget_form_alter Implements hook_field_widget_form_alter().
civicrm_entity_price_set_field_field_widget_info Implements hook_field_widget_info().
civicrm_entity_price_set_field_field_widget_info_alter Implements hook_field_widget_info_alter().
civicrm_entity_price_set_field_form_civicrm_entity_admin_settings_form_alter Implements hook_form_FORM_ID_alter().
civicrm_entity_price_set_field_form_field_ui_field_edit_form_alter Implements hook_form_FORMID_alter().
civicrm_entity_price_set_field_form_field_ui_field_overview_form_alter Implements hook_form_FORMID_alter().
civicrm_entity_price_set_field_inline_entity_form_settings_alter Implements hook_inline_entity_form_settings_alter().
civicrm_entity_price_set_field_rules_action_info Implements hook_rules_action_info() Add a Rules Action for subscribing a user to a node.
civicrm_entity_price_set_field_rules_event_info Implementation of hook_rules_event_info()
civicrm_entity_price_set_field_send_contribution_receipt Sends confirmation email for a Contribution using CiviCRM API sendconfirmation action
civicrm_entity_price_set_field_theme Implements hook_theme().
theme_civicrm_entity_price_set_field_price_field_drag_components Theme function for price field form components
_civicrm_entity_price_set_field_amount_element_validate Element validation handler for price field value amount element of the price set widget
_civicrm_entity_price_set_field_create_new_priceset_data Helper function to setup the price set data area for a new entity
_civicrm_entity_price_set_field_get_relevant_entities Utility function to load the price set and child entities relevant to the widget or display formatter
_civicrm_entity_price_set_field_get_relevant_entities_clone Utility function to load the price set and child entities. This method clones the entity objects so the registration form can alter the values
_civicrm_entity_price_set_field_label_element_validate Element validation handler for price field value label element of the price set widget
_civicrm_entity_price_set_field_prepare_simple_widget Helper function to create FAPI form element for the Simple widget
_civicrm_entity_price_set_field_process_field_items Helper function to process field items on entity update
_civicrm_entity_price_set_field_setup_entities Helper function to setup data structure for price set, price field, price field values, for an event
_civicrm_entity_price_set_field_simple_widget_add_button_submit Submit callback for Price Field Values table add button, Simple Widget
_civicrm_entity_price_set_field_simple_widget_price_field_ajax Ajax callback for Price Field Values table, Simple Widget
_civicrm_entity_price_set_field_simple_widget_remove_button_submit Submit callback for Price Field Values table Remove button , Simple Widget