home | career | drupal | java | mac | mysql | perl | php | scala | uml | unix

Drupal example source code file (ca.admin.inc)

This example Drupal source code file (ca.admin.inc) is included in the DevDaily.com "Drupal Source Code Warehouse" project. The intent of this project is to help you "Learn Drupal by Example".

PHP - Drupal tags/keywords

array, condition, conditions, foreach, form, function, if, key, name, php, predicate, title, type, value

The ca.admin.inc Drupal example source code

<?php
// $Id: ca.admin.inc,v 1.1.2.17 2010/03/13 18:22:26 tr Exp $

/**
 * @file
 * Conditional actions overview UI.
 */

/**
 * Display the administration page that lets you add and modify predicates.
 */
function ca_admin($groupby = 'trigger') {
  drupal_add_css(drupal_get_path('module', 'ca') .'/ca.css');

  // Load all the module defined predicates into a temporary array.
  $temp = module_invoke_all('ca_predicate');

  // Assign a default weight if need be.
  foreach ($temp as $key => $value) {
    $temp[$key]['#pid'] = $key;
    if (!isset($value['#weight'])) {
      $temp[$key]['#weight'] = 0;
    }
  }

  // Load and loop through all the database stored predicates.
  $result = db_query("SELECT * FROM {ca_predicates}");
  while ($predicate = db_fetch_array($result)) {
    // Prepare the database data into a predicate.
    $predicate = ca_prepare_db_predicate($predicate);

    // Overrides the module defined predicate if it's been modified by a user.
    $temp[$predicate['#pid']] = $predicate;
  }

  usort($temp, 'ca_weight_sort');

  // Copy the temporary array of predicates into a keyed array.
  $predicates = array();
  foreach ($temp as $predicate) {
    $predicates[$predicate['#pid']] = $predicate;
  }

  // Load up the trigger data so we can display them by title.
  $triggers = module_invoke_all('ca_trigger');

  // Build the header for the predicate tables based on the grouping type.
  if ($groupby == 'trigger') {
    $header = array(
      array('data' => t('Title'), 'class' => 'col-title'),
      t('Class'),
      t('Status'),
      t('Weight'),
      t('Operations'),
    );

    $table_class = 'ca-predicate-trigger';
    $table_label = '<strong>'. t('Trigger') .':</strong> ';
  }
  elseif ($groupby == 'class') {
    $header = array(
      array('data' => t('Title'), 'class' => 'col-title'),
      t('Trigger'),
      t('Status'),
      t('Weight'),
      t('Operations'),
    );

    $table_class = 'ca-predicate-class';
    $table_label = '<strong>'. t('Class') .':</strong> ';
  }

  $rows = array();

  foreach ($predicates as $key => $value) {
    // Build the basic operation links for each predicate.
    $ops = array(
      l(t('edit'), CA_UI_PATH .'/'. $key .'/edit'),
    );

    // Add the reset link if a module defined predicate has been modified.
    if (!is_numeric($key) && isset($value['#modified'])) {
      $ops[] = l(t('reset'), CA_UI_PATH .'/'. $key .'/reset');
    }

    // Add a delete link if displaying a custom predicate.
    if (is_numeric($key)) {
      $ops[] = l(t('delete'), CA_UI_PATH .'/'. $key .'/delete');
    }

    // Add the predicate's row to the table based on the grouping type.
    if ($groupby == 'trigger') {
      $tables[$triggers[$value['#trigger']]['#title']]['rows'][] = array(
        check_plain($value['#title']),
        strpos($value['#class'], 'custom') === 0 ? check_plain(substr($value['#class'], 7)) : $value['#class'],
        $value['#status'] == 0 ? t('Disabled') : t('Enabled'),
        array('data' => $value['#weight'], 'class' => 'ca-predicate-table-weight'),
        array('data' => implode(' ', $ops), 'class' => 'ca-predicate-table-ops'),
      );
    }
    elseif ($groupby == 'class') {
      $class = strpos($value['#class'], 'custom') === 0 ? check_plain(substr($value['#class'], 7)) : $value['#class'];

      $tables[$class]['rows'][] = array(
        check_plain($value['#title']),
        check_plain($triggers[$value['#trigger']]['#title']),
        $value['#status'] == 0 ? t('Disabled') : t('Enabled'),
        array('data' => $value['#weight'], 'class' => 'ca-predicate-table-weight'),
        array('data' => implode(' ', $ops), 'class' => 'ca-predicate-table-ops'),
      );
    }
  }

  // Put the tables in alphabetical order.
  ksort($tables);

  // Add the tables for each trigger to the output.
  foreach ($tables as $key => $value) {
    // Accommodate empty class names.
    if (empty($key)) {
      $key = t('- None -');
    }

    $output .= theme('table', $header, $value['rows'], array('class' => $table_class), $table_label . check_plain($key));
  }

  $output .= l(t('Add a predicate'), CA_UI_PATH .'/add');

  return $output;
}

/**
 * Form to allow the creation and editing of conditional action predicates.
 */
function ca_predicate_meta_form($form_state, $pid) {
  // Load the predicate if an ID is passed in.
  if (!empty($pid) && $pid !== 0) {
    $predicate = ca_load_predicate($pid);

    // Fail out if we didn't find a predicate for that ID.
    if (empty($predicate)) {
      drupal_set_message(t('That predicate does not exist.'), 'error');
      drupal_goto(CA_UI_PATH);
    }

    drupal_set_title($predicate['#title']);
  }

  $form['predicate_pid'] = array(
    '#type' => 'value',
    '#value' => $pid,
  );

  $form['predicate_title'] = array(
    '#type' => 'textfield',
    '#title' => t('Title'),
    '#description' => t('Enter a title used for display on the overview tables.'),
    '#default_value' => $pid ? $predicate['#title'] : '',
    '#required' => TRUE,
  );

  // Create an array of triggers for the select box.
  $triggers = module_invoke_all('ca_trigger');
  foreach ($triggers as $key => $value) {
    $options[$value['#category']][$key] = $value['#title'];
  }

  $form['predicate_trigger'] = array(
    '#type' => 'select',
    '#title' => t('Trigger'),
    '#description' => t('Select the trigger for this predicate.<br />Cannot be modified if the predicate has conditions or actions.'),
    '#options' => $options,
    '#default_value' => $pid ? $predicate['#trigger'] : '',
    '#disabled' => empty($predicate['#conditions']) && empty($predicate['#actions']) ? FALSE : TRUE,
    '#required' => TRUE,
  );

  $form['predicate_description'] = array(
    '#type' => 'textarea',
    '#title' => t('Description'),
    '#description' => t('Enter a description that summarizes the use and intent of the predicate.'),
    '#default_value' => $pid ? $predicate['#description'] : '',
  );

  // Accommodate the mandatory custom prefix for predicate classes.
  $class = $predicate['#class'];
  if (strpos($class, 'custom') === 0) {
    $class = ltrim(substr($class, 6), ':');
  }

  if (is_numeric($pid)) {
    $form['predicate_class'] = array(
      '#type' => 'textfield',
      '#title' => t('Class'),
      '#description' => t('Classes let you categorize your predicates based on the type of functionality they provide.'),
      '#field_prefix' => 'custom:',
      '#default_value' => $class,
    );
  }
  else {
    $form['predicate_class'] = array(
      '#type' => 'value',
      '#value' => $class,
    );
  }

  $form['predicate_status'] = array(
    '#type' => 'radios',
    '#title' => t('Status'),
    '#description' => t('Disabled predicates will not be processed when their trigger is pulled.'),
    '#options' => array(
      1 => t('Enabled'),
      0 => t('Disabled'),
    ),
    '#default_value' => $pid ? $predicate['#status'] : 1,
  );

  $form['predicate_weight'] = array(
    '#type' => 'weight',
    '#title' => t('Weight'),
    '#description' => t('Predicates will be sorted by weight and processed sequentially.'),
    '#default_value' => ($pid && isset($predicate['#weight'])) ? $predicate['#weight'] : 0,
  );

  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save predicate'),
    '#suffix' => l(t('Cancel'), CA_UI_PATH),
  );

  return $form;
}

/**
 * @see ca_predicate_meta_form()
 */
function ca_predicate_meta_form_submit($form, &$form_state) {
  $form_state['redirect'] = CA_UI_PATH;
  $save = FALSE;

  // Load the original predicate.
  if ($form_state['values']['pid'] !== 0) {
    $predicate = ca_load_predicate($form_state['values']['predicate_pid']);
    $predicate['#pid'] = $form_state['values']['predicate_pid'];
  }

  // Setup a list of fields to check for and apply changes.
  $fields = array('title', 'trigger', 'description', 'class', 'status', 'weight');

  // Compare the values from the form submission with what is already set.
  foreach ($fields as $field) {
    if ($form_state['values']['predicate_'. $field] != $predicate['#'. $field]) {
      $predicate['#'. $field] = $form_state['values']['predicate_'. $field];
      $save = TRUE;
    }
  }

  // Add empty conditions and actions arrays if this is a new predicate.
  if (empty($predicate['#pid'])) {
    $predicate['#pid'] = variable_get('ca_predicates_pid', 1);
    variable_set('ca_predicates_pid', $predicate['#pid'] + 1);
    $predicate['#conditions'] = array();
    $predicate['#actions'] = array();

    // For new predicates, redirect to the conditions tab.
    $form_state['redirect'] = CA_UI_PATH .'/'. $predicate['#pid'] .'/edit/conditions';
  }

  // Check to see if any changes were made and save if necessary.
  if ($save) {
    ca_save_predicate($predicate);
  }

  drupal_set_message(t('Predicate meta data saved.'));
}

/**
 * Form to reset a modified module defined predicate to its original state.
 */
function ca_predicate_delete_form($form_state, $pid) {
  $predicate = ca_load_predicate($pid);

  // Fail if we received an invalid predicate ID.
  if (empty($predicate)) {
    drupal_set_message(t('That predicate does not exist.'), 'error');
    drupal_goto(CA_UI_PATH);
  }

  $form['predicate_pid'] = array(
    '#type' => 'value',
    '#value' => $pid,
  );

  $form['predicate_title'] = array(
    '#type' => 'value',
    '#value' => $predicate['#title'],
  );

  $description = '<p><strong>'. check_plain($predicate['#title']) .'</strong><br />'
               . check_plain($predicate['#description']) .'</p><p>'
                . t('This action cannot be undone.') .'</p>';

  return confirm_form($form, t('Are you sure you want to !op this predicate?', array('!op' => is_numeric($pid) ? t('delete') : t('reset'))), CA_UI_PATH, $description);
}

/**
 * @see ca_predicate_delete_form()
 */
function ca_predicate_delete_form_submit($form, &$form_state) {
  ca_delete_predicate($form_state['values']['predicate_pid']);

  drupal_set_message(t('Predicate %title !op.', array('%title' => $form_state['values']['predicate_title'], '!op' => is_numeric($form_state['values']['predicate_pid']) ? t('deleted') : t('reset'))));

  $form_state['redirect'] = CA_UI_PATH;
}

/**
 * Build a form for adding and editing actions on a predicate.
 *
 * @param $form_state
 *   Used by FAPI; the current state of the form as it processes.
 * @param $pid
 *   The ID of the predicate whose actions are being modified.
 * @param $title
 *   TRUE or FALSE to specify whether or not to set the predicate's title to be
 *     the title of the page.
 * @return
 *   The form array for the actions form.
 *
 * @ingroup forms
 * @see
 *   ca_actions_form_add_action_submit()
 *   ca_actions_form_add_action_submit()
 *   ca_actions_form_save_changes_submit()
 */
function ca_actions_form($form_state, $pid, $title = TRUE) {
  // Locate the specified predicate.
  $predicate = ca_load_predicate($pid);

  // Return an empty form if the predicate does not exist.
  if (empty($predicate)) {
    return array();
  }

  // Include the JS for conditional actions forms.
  drupal_add_js(drupal_get_path('module', 'ca') .'/ca.js');

  // Display the title if appropriate.
  if ($title) {
    drupal_set_title($predicate['#title']);
  }

  // Load up any actions that could possibly be on this predicate.
  $action_data = ca_load_action();

  $form['pid'] = array(
    '#type' => 'value',
    '#value' => $pid,
  );

  $form['actions'] = array(
    '#type' => 'fieldset',
    '#title' => t('Actions'),
    '#description' => t('These actions will be performed in order when this predicate passes the conditions evaluation.'),
    '#tree' => TRUE,
  );

  // Loop through the actions and add them to the form if valid.
  $i = 0;

  foreach ($predicate['#actions'] as $key => $action) {
    // Add it to the form if the action's callback exists.
    $callback = $action_data[$action['#name']]['#callback'];

    if (function_exists($callback)) {
      $form['actions'][$i] = array(
        '#type' => 'fieldset',
        '#title' => t('Action: @title', array('@title' => $action_data[$action['#name']]['#title'])),
        '#description' => $action_data[$action['#name']]['#description'],
        '#collapsible' => TRUE,
        '#collapsed' => isset($_SESSION['ca_action_focus']) && $i == $_SESSION['ca_action_focus'] ? FALSE : TRUE,
      );

      $form['actions'][$i]['name'] = array(
        '#type' => 'value',
        '#value' => $action['#name'],
      );

      $form['actions'][$i]['title'] = array(
        '#type' => 'textfield',
        '#title' => t('Title'),
        '#default_value' => $action['#title'],
      );

      $form['actions'][$i]['argument_map'] = array(
        '#type' => 'fieldset',
        '#title' => t('Arguments'),
        '#description' => t('Some triggers pass in multiple options for arguments related to a particular action, so you must specify which options to use in the fields below.'),
        '#collapsible' => TRUE,
      );

      // Setup a variable to decide if we can collapse the arguments fieldset.
      $collapsed = TRUE;

      foreach ($action_data[$action['#name']]['#arguments'] as $key => $value) {
        // Load the available arguments for each entity as received by the
        // trigger when it was pulled.
        $options = ca_load_trigger_arguments($predicate['#trigger'], $value['#entity']);

        // If we have more than one option for any argument, do not collapse.
        if (count($options) > 1) {
          $collapsed = FALSE;
        }

        $form['actions'][$i]['argument_map'][$key] = array(
          '#type' => 'select',
          '#title' => check_plain($value['#title']),
          '#options' => $options,
          '#default_value' => $action['#argument_map'][$key],
        );
      }

      $form['actions'][$i]['argument_map']['#collapsed'] = $collapsed;

      // Add the action's form elements if any exist.
      $callback .= '_form';

      if (function_exists($callback)) {
        // Load the trigger data.
        $trigger_data = ca_load_trigger($predicate['#trigger']);

        $form['actions'][$i]['settings'] = $callback(array(), $action['#settings'], $trigger_data['#arguments']);
      }

      $form['actions'][$i]['remove'] = array(
        '#type' => 'submit',
        '#value' => t('Remove this action'),
        '#name' => 'ca_remove_action_'. $i,
        '#submit' => array('ca_actions_form_remove_action_submit'),
        '#attributes' => array('class' => 'ca-remove-confirm'),
      );

      $i++;
    }
  }

  // Unset the session variable used to focus on the new action.
  unset($_SESSION['ca_action_focus']);

  $form['actions']['add_action'] = array(
    '#type' => 'select',
    '#title' => t('Available actions'),
    '#options' => ca_load_trigger_actions($predicate['#trigger']),
  );

  $form['actions']['add'] = array(
    '#type' => 'submit',
    '#value' => t('Add action'),
    '#submit' => array('ca_actions_form_add_action_submit'),
  );

  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save changes'),
    '#submit' => array('ca_actions_form_save_changes_submit'),
  );

  filter_configure_form($form);

  return $form;
}

/**
 * Remove action submit handler.
 *
 * @see ca_actions_form()
 */
function ca_actions_form_remove_action_submit($form, &$form_state) {
  // Save the existing actions to preserve any changes.
  ca_actions_form_update_actions($form_state['values']['pid'], $form_state['values']['actions']);

  // Remove the appropriate action from the predicate and save it.
  ca_remove_action($form_state['values']['pid'], $form_state['clicked_button']['#parents'][1]);

  drupal_set_message(t('Action removed.'));
}

/**
 * Add action submit handler.
 *
 * @see ca_actions_form()
 */
function ca_actions_form_add_action_submit($form, &$form_state) {
  // Save the existing actions to preserve any changes.
  $predicate = ca_actions_form_update_actions($form_state['values']['pid'], $form_state['values']['actions']);

  // Store the presumed key of the new action.
  $_SESSION['ca_action_focus'] = count($predicate['#actions']);

  // Add the specified action to the predicate.
  ca_add_action($form_state['values']['pid'], $form_state['values']['actions']['add_action']);

  drupal_set_message(t('Action added.'));
}

/**
 * Save changes submit handler for the actions form.
 *
 * @see ca_actions_form()
 */
function ca_actions_form_save_changes_submit($form, &$form_state) {
  // Save the existing actions to preserve any changes.
  ca_actions_form_update_actions($form_state['values']['pid'], $form_state['values']['actions']);

  drupal_set_message(t('Actions saved.'));
}

/**
 * Updates a predicate's actions based on the values from an actions form.
 *
 * @param $pid
 *   The ID of the predicate whose actions should be updated.
 * @param $data
 *   The actions values from the form state that should be used to update the
 *     predicate; normally $form_state['values']['actions'].
 * @return
 *   An array representing the full, updated predicate.
 */
function ca_actions_form_update_actions($pid, $data) {
  $actions = array();

  // Unset top level components we don't want to get in the way.
  unset($data['add_action'], $data['add']);

  // Loop through the actions from the form and add them to our temporary array.
  foreach ((array) $data as $key => $value) {
    $actions[] = array(
      '#name' => $value['name'],
      '#title' => $value['title'],
      '#argument_map' => $value['argument_map'],
      '#settings' => empty($value['settings']) ? array() : $value['settings'],
    );
  }

  // Load the predicate as it is now.
  $predicate = ca_load_predicate($pid);

  // Update the actions and save the result.
  $predicate['#actions'] = $actions;
  ca_save_predicate($predicate);

  return $predicate;
}

/**
 * Build a form for adding and editing conditions on a predicate.
 *
 * @ingroup forms
 * @see
 *   ca_conditions_form_add_condition_group_submit()
 *   ca_conditions_form_remove_condition_group_submit()
 *   ca_conditions_form_add_condition_submit()
 *   ca_conditions_form_remove_condition_submit()
 *   ca_conditions_form_save_changes_submit()
 */
function ca_conditions_form($form_state, $pid, $title = TRUE) {
  // Locate the specified predicate.
  $predicate = ca_load_predicate($pid);

  // Return an empty form if the predicate does not exist.
  if (empty($predicate)) {
    return array();
  }

  // Include the JS for conditional actions forms.
  drupal_add_js(drupal_get_path('module', 'ca') .'/ca.js');

  // Display the title if appropriate.
  if ($title) {
    drupal_set_title($predicate['#title']);
  }

  // Initialize the conditions available for this predicate.
  ca_load_trigger_conditions($predicate['#trigger']);

  // Add the predicate ID to the form array.
  $form['pid'] = array(
    '#type' => 'value',
    '#value' => $pid,
  );

  // If the predicate conditions array isn't already a container of containers,
  // make it so.  i.e. group => array('group' => array('cond', 'cond'))
  if (empty($predicate['#conditions'])) {
    $predicate['#conditions'] = ca_new_conditions();
  }
  else {
    $key = array_shift(array_keys($predicate['#conditions']['#conditions']));

    if (empty($predicate['#conditions']['#conditions'][$key]['#operator'])) {
      $predicate['#conditions'] = array(
        '#operator' => 'AND',
        '#conditions' => array(
          $predicate['#conditions'],
        ),
      );
    }
  }

  // Recurse through the predicate's conditions to build the form.
  $form['conditions'] = _ca_conditions_form_tree($predicate['#conditions'], $predicate['#trigger']);
  $form['conditions'] = $form['conditions'][0];

  // Always remove the top level condition group controls.
  unset($form['conditions']['condition']);
  unset($form['conditions']['add_condition']);
  unset($form['conditions']['remove_condition_group']);

  // If there are more than one top level condition groups...
  if (count($form['conditions']['conditions']) > 1) {
    // Update the top level fieldset.
    $form['conditions']['#title'] = t('Condition groups');
    $form['conditions']['#collapsible'] = FALSE;

    // Adjust the titles of the operator options to be more explicit.
    $form['conditions']['operator']['#options'] = array(
      'AND' => t('AND. If all of these condition groups are TRUE.'),
      'OR' => t('OR. If any of these condition groups are TRUE.'),
    );
  }
  else {
    // Otherwise remove the top level fieldset and operator.
    unset($form['conditions']['#type']);
    unset($form['conditions']['operator']);

    // Adjust the second level conditions group to not collapse.
    $form['conditions']['conditions'][0]['#collapsible'] = FALSE;
  }

  // Set the conditions array to a tree so the submitted form values mirror the
  // structure of a predicate's #conditions array.
  $form['conditions']['#tree'] = TRUE;

  $form['save'] = array(
    '#type' => 'submit',
    '#value' => t('Save changes'),
    '#submit' => array('ca_conditions_form_save_changes_submit'),
  );

  $form['add_condition_group'] = array(
    '#type' => 'submit',
    '#value' => t('Add condition group'),
    '#submit' => array('ca_conditions_form_add_condition_group_submit'),
  );

  filter_configure_form($form);

  return $form;
}

/**
 * Recursively add logical groups to the conditions form as fieldsets.
 *
 * @param $condition
 *   An array consisting of an #operator and another array of #conditions, or
 *   a condition array with data pertaining to its callback function.
 * @param $trigger
 *   The trigger name and data concerning the arguments that are passed in to
 *   the condition.
 * @return
 *   A form array representing the tree of conditions.
 */
function _ca_conditions_form_tree($condition, $trigger) {
  // We need an index so condition group fieldsets have unique keys.
  static $index = 0;
  $form = array();

  // If we're dealing with a conditions group and not a single condition.
  if (isset($condition['#operator']) && is_array($condition['#conditions'])) {
    $level = $index;

    $form[$level] = array(
      '#type' => 'fieldset',
      '#title' => t('Conditions group'),
      '#collapsible' => TRUE,
    );

    // Add an operator radio select for the group.
    $form[$level]['operator'] = array(
      '#type' => 'radios',
      '#title' => t('Operator'),
      '#options' => array(
        'AND' => t('AND. If all of these conditions are TRUE.'),
        'OR' => t('OR. If any of these conditions are TRUE.'),
      ),
      '#default_value' => $condition['#operator'],
    );

    $form[$level]['conditions'] = array();

    // For each condition in #conditions, add a condition fieldset to the form.
    foreach ($condition['#conditions'] as $sub_condition) {
      $result = _ca_conditions_form_tree($sub_condition, $trigger);

      if (is_array($result)) {
        $form[$level]['conditions'] = array_merge($form[$level]['conditions'], $result);
      }
    }

    $form[$level]['condition'] = array(
      '#type' => 'select',
      '#title' => t('Available conditions'),
      '#options' => ca_load_trigger_conditions(),
    );
    $form[$level]['add_condition'] = array(
      '#type' => 'submit',
      '#value' => t('Add condition'),
      '#submit' => array('ca_conditions_form_add_condition_submit'),
      '#name' => 'add_condition_'. $level,
    );
    $form[$level]['remove_condition_group'] = array(
      '#type' => 'submit',
      '#value' => t('Remove group'),
      '#submit' => array('ca_conditions_form_remove_condition_group_submit'),
      '#attributes' => array('class' => 'ca-remove-confirm'),
      '#name' => 'remove_condition_group_'. $level,
    );

    $index++;

    return $form;
  }
  elseif (!empty($condition)) {
    // Load the data for the conditions as defined by modules.
    $condition_data = ca_load_condition();

    // Otherwise add a fieldset for the individual condition.
    $form[0] = array(
      '#type' => 'fieldset',
      '#title' => t('Condition: @title', array('@title' => $condition_data[$condition['#name']]['#title'])),
      '#description' => t('@description', array('@description' => $condition_data[$condition['#name']]['#description'])),
      '#collapsible' => TRUE,
      '#collapsed' => isset($condition['#expanded']) ? FALSE : TRUE,
    );

    // Add form elements to the fieldset to adjust the condition's settings.
    $form[0] += _ca_conditions_form_condition($condition, $trigger);

    return $form;
  }
}

/**
 * Add a single condition's fieldset to the conditions form.
 *
 * @param $condition
 *   The condition data array.
 * @param $trigger
 *   The trigger name and data concerning the arguments that are passed in to
 *   the condition.
 * @return
 *   A form array representing the condition.
 */
function _ca_conditions_form_condition($condition, $trigger) {
  static $identifier = 0;

  // Load the data for the conditions as defined by modules.
  $condition_data = ca_load_condition();

  // Condition name is a hard reference to the condition and so not editable.
  $form['name'] = array(
    '#type' => 'value',
    '#value' => $condition['#name'],
  );

  // The title for this particular instance of this condition.
  $form['title'] = array(
    '#type' => 'textfield',
    '#title' => t('Title'),
    '#default_value' => $condition['#title'],
  );

  $form['argument_map'] = array(
    '#type' => 'fieldset',
    '#title' => t('Arguments'),
    '#description' => t('Some triggers pass in multiple options for arguments related to a particular condition, so you must specify which options to use in the fields below.'),
    '#collapsible' => TRUE,
  );

  // Setup a variable to decide if we can collapse the arguments fieldset.
  $collapsed = TRUE;

  // Cast to an array to accommodate conditions that need no arguments.
  foreach ((array) $condition_data[$condition['#name']]['#arguments'] as $key => $value) {
    // Load the available arguments for each entity as received by the
    // trigger when it was pulled.
    $options = ca_load_trigger_arguments($trigger, $value['#entity']);

    // If we have more than one option for any argument, do not collapse.
    if (count($options) > 1) {
      $collapsed = FALSE;
    }

    $form['argument_map'][$key] = array(
      '#type' => 'select',
      '#title' => check_plain($value['#title']),
      '#options' => $options,
      '#default_value' => $condition['#argument_map'][$key],
    );
  }

  $form['argument_map']['#collapsed'] = $collapsed;

  // Whether or not to negate the result of this condition.
  $form['settings']['negate'] = array(
    '#type' => 'checkbox',
    '#title' => t('Negate this condition.'),
    '#description' => t('Return FALSE if the condition is TRUE and vice versa.'),
    '#default_value' => $condition['#settings']['negate'],
  );

  // Get the callback for the condition we're displaying.
  $callback = $condition_data[$condition['#name']]['#callback'] .'_form';

  if (function_exists($callback)) {
   // Load the trigger data.
   $trigger_data = ca_load_trigger($trigger);

  // Add the condition's form elements to the fieldset.
    $form['settings'] += $callback(array(), $condition['#settings'], $trigger_data['#arguments']);
  }

  $form['remove'] = array(
    '#type' => 'submit',
    '#value' => t('Remove this condition'),
    '#submit' => array('ca_conditions_form_remove_condition_submit'),
    '#attributes' => array('class' => 'ca-remove-confirm'),
    '#name' => 'remove_condition_group_'. $identifier++,
  );

  return $form;
}

/**
 * Submit handler for button to add a condition group.
 *
 * @see ca_conditions_form()
 */
function ca_conditions_form_add_condition_group_submit($form, &$form_state) {
  // Save the existing conditions to preserve any changes.
  ca_conditions_form_update_conditions($form_state['values']['pid'], $form_state['values']['conditions']);

  // Add the condition group to the predicate.
  ca_add_condition_group($form_state['values']['pid']);

  // Display a confirmation message.
  drupal_set_message(t('Condition group added.'));
}

/**
 * Submit handler for button to remove a condition grou.
 *
 * @see ca_conditions_form()
 */
function ca_conditions_form_remove_condition_group_submit($form, &$form_state) {
  $group_key = FALSE;

  // Loop through the array keys of the conditions group.
  foreach (array_keys($form['conditions']['conditions']) as $key => $value) {
    // If we find the key we're looking for...
    if (is_numeric($value) && $value == $form_state['clicked_button']['#array_parents'][2]) {
      // Store its position as the new group key once the conditions are saved.
      // This is necessary because the save function will truncate any holes so
      // the keys are in numerical order starting with 0.
      $group_key = $key;
    }
  }

  // Save the existing conditions to preserve any changes.
  ca_conditions_form_update_conditions($form_state['values']['pid'], $form_state['values']['conditions']);

  // Fail if we didn't find a new group key for some reason.
  if ($group_key === FALSE) {
    drupal_set_message(t('An error occurred when trying to add the condition.  Please try again.'), 'error');
  }
  else {
    // Remove the condition group from the predicate.
    ca_remove_condition_group($form_state['values']['pid'], $group_key);

    // Display a confirmation message.
    drupal_set_message(t('Condition group removed.'));
  }
}

/**
 * Submit handler for button to add a condition to a condition group.
 *
 * @see ca_conditions_form()
 */
function ca_conditions_form_add_condition_submit($form, &$form_state) {
  $group_key = FALSE;

  // Loop through the array keys of the conditions group.
  foreach (array_keys($form['conditions']['conditions']) as $key => $value) {
    // If we find the key we're looking for...
    if (is_numeric($value) && $value == $form_state['clicked_button']['#array_parents'][2]) {
      // Store its position as the new group key once the conditions are saved.
      // This is necessary because the save function will truncate any holes so
      // the keys are in numerical order starting with 0.
      $group_key = $key;
    }
  }

  // Save the existing conditions to preserve any changes.
  ca_conditions_form_update_conditions($form_state['values']['pid'], $form_state['values']['conditions']);

  // Fail if we didn't find a new group key for some reason.
  if ($group_key === FALSE) {
    drupal_set_message(t('An error occurred when trying to add the condition.  Please try again.'), 'error');
  }
  else {
    // Otherwise add the condition to the specified group.
    $name = $form_state['values']['conditions']['conditions'][$group_key]['condition'];

    ca_add_condition($form_state['values']['pid'], $name, $group_key);

    $condition = ca_load_condition($name);

    drupal_set_message(t('%title condition added.', array('%title' => $condition['#title'])));
  }
}

/**
 * Submit handler for button to remove a condition from a condition group.
 *
 * @see ca_conditions_form()
 */
function ca_conditions_form_remove_condition_submit($form, &$form_state) {
  $group_key = FALSE;
  $cond_key = FALSE;

  // Loop through the array keys of the conditions group.
  foreach (array_keys($form['conditions']['conditions']) as $key => $value) {
    // If we find the key we're looking for...
    if (is_numeric($value) && $value == $form_state['clicked_button']['#array_parents'][2]) {
      // Store its position as the new group key once the conditions are saved.
      // This is necessary because the save function will truncate any holes so
      // the keys are in numerical order starting with 0.
      $group_key = $key;
    }
  }

  // Loop through the array keys of the conditions in the group.
  foreach (array_keys($form['conditions']['conditions'][$form_state['clicked_button']['#array_parents'][2]]['conditions']) as $key => $value) {
    // If we find the key we're looking for...
    if (is_numeric($value) && $value == $form_state['clicked_button']['#array_parents'][4]) {
      // Store its position as the new condition key once the conditions are
      // saved. This is necessary because the save function will truncate any
      // holes so the keys are in numerical order starting with 0.
      $cond_key = $key;
    }
  }

  // Save the existing conditions to preserve any changes.
  ca_conditions_form_update_conditions($form_state['values']['pid'], $form_state['values']['conditions']);

  // Fail if we didn't find a new group key for some reason.
  if ($group_key === FALSE || $cond_key === FALSE) {
    drupal_set_message(t('An error occurred when trying to remove the condition.  Please try again.'), 'error');
  }
  else {
    // Otherwise remove the condition from the specified group.
    ca_remove_condition($form_state['values']['pid'], $group_key, $cond_key);

    drupal_set_message(t('Condition removed.'));
  }
}

/**
 * Save changes submit handler for the conditions form.
 *
 * @see ca_conditions_form()
 */
function ca_conditions_form_save_changes_submit($form, &$form_state) {
  // Save the existing conditions to preserve any changes.
  ca_conditions_form_update_conditions($form_state['values']['pid'], $form_state['values']['conditions']);

  drupal_set_message(t('Conditions saved.'));
}

/**
 * Update a predicate's conditions based on the values from a conditions form.
 *
 * @param $pid
 *   The ID of the predicate whose conditions should be updated.
 * @param $data
 *   The conditions values from the form state that should be used to update the
 *     predicate; normally $form_state['values']['conditions'].
 * @return
 *   An array representing the full, updated predicate.
 */
function ca_conditions_form_update_conditions($pid, $data) {
  // Build the new conditions array from scratch.
  $conditions = ca_new_conditions();

  // Override the top level operator if need be.
  if (isset($data['operator'])) {
    $conditions['#operator'] = $data['operator'];
  }

  // Use a variable to track the group array key so we can "reset" the keys.
  $group = 0;

  // Loop through each second level condition group.
  foreach ($data['conditions'] as $key => $value) {
    // Save the operator setting.
    $conditions['#conditions'][$group]['#operator'] = $value['operator'];
    $conditions['#conditions'][$group]['#conditions'] = array();

    // If conditions exist...
    if (is_array($value['conditions']) && count($value['conditions']) > 0) {
      // Use a variable to track the condition array key as for groups.
      $condition = 0;

      // Loop through the conditions in this group.
      foreach ($value['conditions'] as $cond_key => $cond_value) {
        // Save the condition's settings.
        $conditions['#conditions'][$group]['#conditions'][$condition] = array(
          '#name' => $cond_value['name'],
          '#title' => $cond_value['title'],
          '#argument_map' => $cond_value['argument_map'],
          '#settings' => $cond_value['settings'],
        );

        $condition++;
      }
    }

    $group++;
  }

  // Load the predicate as it is now.
  $predicate = ca_load_predicate($pid);

  // Update the actions and save the result.
  $predicate['#conditions'] = $conditions;
  ca_save_predicate($predicate);

  return $predicate;
}

/**
 * Landing page for converting Workflow-ng configurations.
 *
 * From this page, the user can begin the batch processing of any Workflow-ng
 * configurations in the site's database into Conditional Actions predicates.
 *
 * @ingroup forms
 * @see ca_conversion_form_submit()
 */
function ca_conversion_form() {
  $form = array();

  $form['help'] = array(
    '#value' => '<div>'. t('Use this form during the update process from Ubercart 1.0 to 2.0 to convert your Workflow-ng configurations to Conditional Actions predicates.  Once your configurations are converted, you should complete your uninstallation of Workflow-ng.') .'</div>',
  );

  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Convert configurations'),
  );

  return $form;
}

/**
 * @see ca_conversion_form_submit()
 */
function ca_conversion_form_submit($form, &$form_state) {
  // Convert workflow-ng configurations in a batch process because there may be
  // a lot of them.
  $batch = array(
    'operations' => array(
      array('_ca_convert_configurations', array()),
    ),
    'finished' => '_ca_conversion_finished',
    'title' => t('Converting Workflow-ng configurations'),
    'init_message' => t('Beginning conversion...'),
    'progress_message' => t('@percentage% converted'),
    'file' => drupal_get_path('module', 'ca') . '/ca.admin.inc',
  );

  batch_set($batch);
}

/**
 * Batch API callback for Workflow-ng configuration conversion.
 */
function _ca_convert_configurations(&$context) {
  global $user;

  if (db_table_exists('workflow_ng_cfgs')) {
    if (!isset($context['sandbox']['progress'])) {
      // Initialize batch data.
      $context['sandbox']['progress'] = 0;
      $context['sandbox']['current_cfg'] = '';
      $context['sandbox']['max'] = db_result(db_query("SELECT COUNT(name) FROM {workflow_ng_cfgs} WHERE altered = 1"));
    }

    $limit = 25;

    $result = db_query_range("SELECT name, data FROM {workflow_ng_cfgs} WHERE altered = 1 AND name > '%s' ORDER BY name", $context['sandbox']['current_cfg'], 0, $limit);
    $predicates = array();

    while ($configuration_row = db_fetch_object($result)) {
      $predicate = array('#pid' => $configuration_row->name);
      $conditions = array();
      $actions = array();
      if ($configuration = unserialize($configuration_row->data)) {
        $predicate['#class'] = $configuration['#module'];
        $predicate['#title'] = $configuration['#label'];

        // Convert event names to corresponding triggers.
        switch ($configuration['#event']) {
          case 'order_status_update':
            $trigger = 'uc_order_status_update';
          break;
          case 'payment_entered':
            $trigger = 'uc_payment_entered';
          break;
          case 'checkout_complete':
            $trigger = 'uc_checkout_complete';
          break;
          default:
            $trigger = $configuration['#event'];
          break;
        }

        // In UC 1.x, taxes had an event for each tax rate, using the same
        // action. In UC 2.x, they use the same trigger, but have separate
        // actions.
        if (strpos($trigger, 'calculate_tax_') === 0) {
          $tax_id = substr($trigger, 14);
          $trigger = 'calculate_taxes';
        }

        $predicate['#trigger'] = $trigger;
        $predicate['#weight'] = $configuration['#weight'];
        $predicate['#status'] = $configuration['#active'];

        // Numeric keys in $configuration could be for conditions or actions.
        // Take each and categorize them to add them to the predicate later.
        for ($i = 0; isset($configuration[$i]); $i++) {
          if ($configuration[$i]['#type'] == 'action') {
            $action = _ca_convert_actions($configuration[$i], $tax_id);
            if ($action) {
              $actions[] = $action;
            }
          }
          else {
            $condition = _ca_convert_conditions($configuration[$i]);
            if ($condition) {
              $conditions[] = $condition;
            }
          }
        }

        // Conditions are optional. If there are no actions, there's no reason
        // to make a predicate.
        if ($conditions) {
          $predicate['#conditions'] = array(
            '#operator' => 'AND',
            '#conditions' => $conditions,
          );
        }
        if ($actions) {
          $predicate['#actions'] = $actions;
          $predicate['#uid'] = $user->uid;
          ca_save_predicate($predicate);
        }
      }

      // Store some result for post-processing in the finished callback.
      $context['results'][] = $configuration_row->name;

      // Update our progress information.
      $context['sandbox']['progress']++;
      $context['sandbox']['current_cfg'] = $configuration_row->name;
      $context['message'] = t('Now processing %cfg', array('%cfg' => $configuration_row->name));
    }

    // Inform the batch engine that we are not finished,
    // and provide an estimation of the completion level we reached.
    if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
      $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
    }
  }
}

/**
 * Helper function for converting Ubercart's Workflow-ng conditions.
 */
function _ca_convert_conditions($condition_tree) {
  static $condition_data;
  $ca_condition = array();

  if (!isset($condition_data)) {
    $condition_data = module_invoke_all('ca_condition');
  }

  // Handle multiple conditions recursively.
  if ($condition_tree['#type'] == 'AND' || $condition_tree['#type'] == 'OR') {
    $ca_condition['#operator'] = $condition_tree['#type'];
    $ca_condition['#conditions'] = array();
    for ($i = 0; isset($condition_tree[$i]); $i++) {
      $condition = _ca_convert_conditions($condition_tree[$i]);
      if ($condition) {
        $ca_condition['#conditions'][] = $condition;
      }
    }
  }
  else if ($condition_tree['#type'] == 'condition') {
    // Some conditions were renamed but check the same things.
    switch ($condition_tree['#name']) {
      case 'uc_order_condition_order_total':
        $ca_condition['#name'] = 'uc_order_condition_total';
        break;
      case 'uc_payment_condition_balance':
        $ca_condition['#name'] = 'uc_payment_condition_order_balance';
        break;
      case 'workflow_ng_condition_custom_php':
        $ca_condition['#name'] = 'ca_condition_custom_php';
        break;
      case 'workflow_ng_condition_user_hasrole':
        $ca_condition['#name'] = 'ca_condition_user_roles';
        $condition_tree['#settings']['operator'] = $condition_tree['#settings']['operation'];
        unset($condition_tree['#settings']['operation']);
        break;
      default:
        $ca_condition['#name'] = $condition_tree['#name'];
        break;
    }

    if (isset($condition_tree['#label'])) {
      $ca_condition['#title'] = $condition_tree['#label'];
    }
    else {
      $ca_condition['#title'] = $condition_data[$ca_condition['#name']]['#title'];
    }

    $ca_condition['#argument_map'] = $condition_tree['#argument map'];
    foreach ($ca_condition['#argument_map'] as $key => $value) {
      if ($key == 'user') {
        $key = 'account';
      }
      if ($value == 'user') {
        $value = 'account';
      }
      $ca_condition['#argument_map'][$key] = $value;
    }

    $ca_condition['#settings'] = $condition_tree['#settings'];
    if (isset($condition_tree['#negate'])) {
      $ca_condition['#settings']['negate'] = $condition_tree['#negate'];
    }
  }

  return $ca_condition;
}

/**
 * Helper function for converting Ubercart's Workflow-ng actions.
 */
function _ca_convert_actions($wf_action, $tax_id = NULL) {
  static $action_data;
  $action = $wf_action;

  if (!isset($action_data)) {
    $action_data = module_invoke_all('ca_action');
  }

  // Some actions were renamed, but do the same things.
  switch ($action['#name']) {
    case 'uc_order_action_update_status':
      $action['#name'] = 'uc_order_update_status';
      break;
    case 'uc_taxes_action_apply_tax':
      $action['#name'] = 'uc_taxes_action_apply_tax_'. $tax_id;
      break;
    case 'workflow_ng_action_custom_php':
      $action['#name'] = 'ca_action_custom_php';
      break;
  }

  if (isset($action['#label'])) {
    $action['#title'] = $action['#label'];
    unset($action['#label']);
  }
  else {
    $action['#title'] = $action_data[$action['#name']]['#title'];
  }

  return $action;
}

/**
 * Batch finalization function to hide the conversion tab.
 */
function _ca_conversion_finished() {
  // Set a variable to hide the conversion tab.
  variable_set('ca_show_conversion_tab', FALSE);

  // Display a message and redirect to the overview page.
  drupal_set_message('Your Workflow-ng configurations have been converted.  Please verify the results in your Conditional Actions predicates below.');

  drupal_goto(CA_UI_PATH);
}

Other Drupal examples (source code examples)

Here is a short list of links related to this Drupal ca.admin.inc source code file:

new blog posts

"Drupal" is a registered trademark of Dries Buytaert.

my drupal tutorials and examples  

Copyright 1998-2016 Alvin Alexander, alvinalexander.com
All Rights Reserved.

Beginning in 2016, a portion of the proceeds from pages under the '/drupal-code-examples/' URI will be donated to charity.