You are here

farm_plan_consideration.module in farmOS 7

Farm plan consideration module.

File

modules/farm/farm_plan/farm_plan_consideration/farm_plan_consideration.module
View source
<?php

/**
 * @file
 * Farm plan consideration module.
 */

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

  // List planning considerations.
  $items['farm/plan/%farm_plan/considerations'] = array(
    'title' => 'Considerations',
    'description' => 'Identify considerations that will affect the planning process.',
    'page callback' => 'farm_plan_consideration_list',
    'page arguments' => array(
      2,
    ),
    'access callback' => 'farm_plan_access',
    'access arguments' => array(
      'update',
      2,
    ),
    'type' => MENU_LOCAL_TASK,
  );

  // Add a new consideration.
  $items['farm/plan/%farm_plan/considerations/add'] = array(
    'title' => 'Add a consideration',
    'description' => 'Add a new planning consideration.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'farm_plan_consideration_form',
      2,
    ),
    'access callback' => 'farm_plan_access',
    'access arguments' => array(
      'update',
      2,
    ),
    'type' => MENU_LOCAL_ACTION,
  );

  // Edit an existing consideration.
  $items['farm/plan/%farm_plan/considerations/%/edit'] = array(
    'title' => 'Edit consideration',
    'description' => 'Edit an existing consideration.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'farm_plan_consideration_form',
      2,
      4,
    ),
    'access callback' => 'farm_plan_access',
    'access arguments' => array(
      'update',
      2,
    ),
  );

  // Delete a consideration.
  $items['farm/plan/%farm_plan/considerations/%/delete'] = array(
    'title' => 'Delete consideration',
    'description' => 'Delete a consideration.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'farm_plan_consideration_delete_form',
      2,
      4,
    ),
    'access callback' => 'farm_plan_access',
    'access arguments' => array(
      'update',
      2,
    ),
  );
  return $items;
}

/**
 * Get available consideration types provided by modules.
 *
 * @return array
 *   Returns an array of consideration type information.
 */
function farm_plan_consideration_types() {

  // Ask modules for consideration types. Use static caching.
  $consideration_types =& drupal_static(__FUNCTION__);
  if (!isset($consideration_types)) {
    $consideration_types = module_invoke_all('farm_plan_consideration_types');
  }

  // Return consideration types.
  return $consideration_types;
}

/**
 * Implements hook_farm_plan_consideration_types().
 */
function farm_plan_farm_plan_consideration_types() {

  // Provide two basic consideration types: "Management concern" and "Urgent".
  return array(
    'concern' => array(
      'label' => t('Management concern'),
      'color' => 'purple',
    ),
    'urgent' => array(
      'label' => t('Urgent'),
      'color' => 'red',
    ),
  );
}

/**
 * Create a new consideration.
 *
 * @param string $type
 *   The consideration type machine name.
 * @param string $name
 *   The consideration name.
 * @param int $start_time
 *   The start timestamp of the consideration.
 * @param int $end_time
 *   The end timestamp of the consideration.
 * @param int $plan_id
 *   The ID of the plan this consideration is linked to (optional).
 *
 * @return object
 *   Returns an empty consideration object.
 */
function farm_plan_consideration_create($type = 'concern', $name = '', $start_time = 0, $end_time = 0, $plan_id = NULL) {
  $consideration = new stdClass();
  $consideration->id = NULL;
  $consideration->type = $type;
  $consideration->name = $name;
  $consideration->plan_id = $plan_id;
  $consideration->start_time = $start_time;
  $consideration->end_time = $end_time;
  $consideration->entities = array();
  return $consideration;
}

/**
 * Save a consideration to the database.
 *
 * @param object $consideration
 *   The consideration object.
 */
function farm_plan_consideration_save(&$consideration) {

  // Build the primary keys parameter for drupal_write_record() depending on
  // whether or not the consideration has an ID (insert vs update).
  $keys = array();
  if (!empty($consideration->id)) {
    $keys[] = 'id';
  }

  // Save the consideration to the database.
  drupal_write_record('farm_plan_consideration', $consideration, $keys);

  // Save all entity links to the consideration.
  if (!empty($consideration->id)) {

    // First delete all existing links.
    db_query('DELETE FROM {farm_plan_consideration_entity} WHERE consideration_id = :id', array(
      ':id' => $consideration->id,
    ));

    // If there are links to save, iterate through them.
    if (!empty($consideration->entities)) {
      foreach ($consideration->entities as $entity_type => $entity_ids) {
        if (!empty($entity_ids)) {
          foreach ($entity_ids as $entity_id) {

            // Save the entity+consideration link.
            $record = array(
              'consideration_id' => $consideration->id,
              'entity_type' => $entity_type,
              'entity_id' => $entity_id,
            );
            drupal_write_record('farm_plan_consideration_entity', $record);
          }
        }
      }
    }
  }
}

/**
 * Load a consideration from the database.
 *
 * @param int $id
 *   The consideration ID.
 *
 * @return object|bool
 *   Returns the consideration object, or FALSE if one doesn't exist.
 */
function farm_plan_consideration_load($id) {

  // Load the consideration record from the database.
  $consideration = db_query('SELECT * FROM {farm_plan_consideration} WHERE id = :id', array(
    ':id' => $id,
  ))
    ->fetch();

  // If a consideration couldn't be loaded, bail.
  if (empty($consideration)) {
    return FALSE;
  }

  // Load entity associations with this consideration.
  $result = db_query('SELECT * FROM {farm_plan_consideration_entity} WHERE consideration_id = :id', array(
    ':id' => $id,
  ));
  foreach ($result as $record) {
    $consideration->entities[$record->entity_type][] = $record->entity_id;
  }

  // Return the consideration.
  return $consideration;
}

/**
 * Delete a consideration from the database.
 *
 * @param int $id
 *   The consideration ID.
 */
function farm_plan_consideration_delete($id) {

  // If the ID is empty, bail.
  if (empty($id)) {
    return;
  }

  // Delete the consideration.
  db_query('DELETE FROM {farm_plan_consideration} WHERE id = :id', array(
    ':id' => $id,
  ));

  // Delete any entity associations to that consideration.
  db_query('DELETE FROM {farm_plan_consideration_entity} WHERE consideration_id = :id', array(
    ':id' => $id,
  ));
}

/**
 * Page callback for considerations list, filtered for a plan.
 *
 * @param $plan
 *   The plan object to filter considerations for..
 *
 * @return string
 *   Return the content of the page.
 */
function farm_plan_consideration_list($plan) {

  // Set the page title.
  drupal_set_title(t('Considerations'));

  // Create a fieldset for the considerations.
  $build['considerations'] = array(
    '#type' => 'fieldset',
    '#title' => t('Planning considerations'),
    '#description' => t('Use this to define any planning considerations you want to remember. Considerations can be specific to a single plan, or they can apply to all plans.'),
  );

  // Define the considerations table header.
  $header = array(
    t('Consideration'),
    t('Type'),
    t('Start'),
    t('End'),
    t('Associations'),
    t('Plan'),
    t('Actions'),
  );

  // Load information about all consideration types.
  $consideration_types = farm_plan_consideration_types();

  // Query all considerations from the database that either apply to all plans,
  // or are associated with this plan specifically, and build a set of rows for
  // the table.
  $rows = array();
  $result = db_query('SELECT id FROM {farm_plan_consideration} WHERE plan_id IS NULL OR plan_id = :plan_id', array(
    ':plan_id' => $plan->id,
  ));
  foreach ($result as $record) {

    // Load the consideration.
    $consideration = farm_plan_consideration_load($record->id);

    // If the consideration didn't load, skip it.
    if (empty($consideration)) {
      continue;
    }

    // Sanitize the name.
    $name = check_plain($consideration->name);

    // Get the consideration type label.
    $type = $consideration->type;
    if (!empty($consideration_types[$type]['label'])) {
      $type = $consideration_types[$type]['label'];
    }

    // Format the start and end dates.
    $date_format = 'M j Y';
    $start_time = date($date_format, $consideration->start_time);
    $end_time = date($date_format, $consideration->end_time);

    // If there are entity associations, build a list.
    $associations = '';
    $entity_links = array();
    if (!empty($consideration->entities)) {
      foreach ($consideration->entities as $entity_type => $ids) {
        foreach ($ids as $id) {
          $entities = entity_load($entity_type, array(
            $id,
          ));
          if (empty($entities)) {
            continue;
          }
          $entity = reset($entities);
          $label = entity_label($entity_type, $entity);
          $uri = entity_uri($entity_type, $entity);
          $entity_links[] = l($label, $uri['path']);
        }
      }
    }
    if (!empty($entity_links)) {
      $associations = theme('item_list', array(
        'items' => $entity_links,
      ));
    }

    // If the consideration is linked to a plan, show a link to it. Otherwise,
    // just say "all".
    $plan_link = 'all';
    if (!empty($consideration->plan_id)) {
      $consideration_plan = farm_plan_load($consideration->plan_id);
      if (!empty($plan)) {
        $plan_label = entity_label('farm_plan', $consideration_plan);
        $plan_uri = entity_uri('farm_plan', $consideration_plan);
        $plan_link = l($plan_label, $plan_uri['path']);
      }
    }

    // Build the actions.
    $actions = array();
    $actions[] = l(t('Edit'), 'farm/plan/' . $plan->id . '/considerations/' . $consideration->id . '/edit');
    $actions[] = l(t('Delete'), 'farm/plan/' . $plan->id . '/considerations/' . $consideration->id . '/delete');
    $actions = implode(' | ', $actions);

    // Assemble the row.
    $row = array(
      $name,
      $type,
      $start_time,
      $end_time,
      $associations,
      $plan_link,
      $actions,
    );

    // Add it to the rows array.
    $rows[] = $row;
  }

  // Build the table render array.
  $build['considerations']['table'] = array(
    '#theme' => 'table',
    '#header' => $header,
    '#rows' => $rows,
    '#empty' => t('No considerations found.'),
  );
  return $build;
}

/**
 * Build the farm plan considerations form.
 */
function farm_plan_consideration_form($form, &$form_state, $plan, $consideration_id = NULL) {

  // Set the page title.
  if (empty($consideration_id)) {
    $title = t('Add a consideration');
  }
  else {
    $title = t('Edit consideration');
  }
  drupal_set_title($title);

  // Store the plan in the form for future use.
  $form['plan'] = array(
    '#type' => 'value',
    '#value' => $plan,
  );

  // Load the consideration record, if one is specified.
  if (!empty($consideration_id)) {
    $consideration = farm_plan_consideration_load($consideration_id);
  }
  else {
    $consideration = farm_plan_consideration_create();
  }

  // Store the consideration in the form for future use.
  $form['consideration'] = array(
    '#type' => 'value',
    '#value' => $consideration,
  );

  // Build an array of consideration type options.
  $consideration_types = farm_plan_consideration_types();
  $consideration_type_options = array();
  foreach ($consideration_types as $type => $info) {
    if (!empty($info['label'])) {
      $consideration_type_options[$type] = $info['label'];
    }
  }

  // Consideration type.
  $form['type'] = array(
    '#type' => 'select',
    '#title' => t('Consideration type'),
    '#description' => t('Specify what type of consideration this is.'),
    '#options' => $consideration_type_options,
    '#default_value' => !empty($consideration->type) ? $consideration->type : 'concern',
    '#required' => TRUE,
    '#ajax' => array(
      'callback' => 'farm_plan_consideration_form_ajax',
      'wrapper' => 'consideration-extra',
    ),
  );

  // Name.
  $form['name'] = array(
    '#type' => 'textfield',
    '#title' => t('Name'),
    '#description' => t('Provide a brief name for this consideration to describe it.'),
    '#default_value' => !empty($consideration->name) ? $consideration->name : '',
    '#required' => TRUE,
  );

  // Define date format.
  $date_format = 'Y-m-d';

  // Start date.
  $default_start_time = !empty($consideration->start_time) ? date($date_format, $consideration->start_time) : '';
  $form['start_time'] = array(
    '#type' => 'date_select',
    '#title' => t('Start date'),
    '#date_label_position' => 'within',
    '#date_format' => $date_format,
    '#date_year_range' => '-3:+10',
    '#default_value' => $default_start_time,
    '#required' => TRUE,
  );

  // End date.
  $default_end_time = !empty($consideration->end_time) ? date($date_format, $consideration->end_time) : '';
  $form['end_time'] = array(
    '#type' => 'date_select',
    '#title' => t('End date'),
    '#date_label_position' => 'within',
    '#date_format' => $date_format,
    '#date_year_range' => '-3:+10',
    '#default_value' => $default_end_time,
    '#required' => TRUE,
  );

  // Is this consideration specific to a plan?
  $plan_label = entity_label('farm_plan', $plan);
  if (!empty($consideration_id)) {
    if (!empty($consideration->plan_id)) {
      $form['plan_id'] = array(
        '#type' => 'markup',
        '#markup' => '<p><strong>' . t('This consideration is specific to plan %plan_label.', array(
          '%plan_label' => $plan_label,
        )) . '</strong></p>',
      );
    }
    else {
      $form['plan_id'] = array(
        '#type' => 'markup',
        '#markup' => '<p><strong>' . t('This consideration applies to all plans.') . '</p></strong>',
      );
    }
  }
  else {
    $form['plan_id'] = array(
      '#type' => 'checkbox',
      '#title' => t('Is this consideration specific to plan %plan_label?', array(
        '%plan_label' => $plan_label,
      )),
      '#description' => t('If this is checked, the consideration will only be visible in the context of this plan. Otherwise, it will be visible to all plans.'),
      '#default_value' => FALSE,
    );
  }

  // Add an area for extra fields. Modules can use this to add type-specific
  // configuration for their consideration types. For example: linking them
  // to entities.
  $form['extra'] = array(
    '#prefix' => '<div id="consideration-extra">',
    '#suffix' => '</div>',
  );

  // Submit button.
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save consideration'),
  );
  return $form;
}

/**
 * Consideration form ajax callback.
 */
function farm_plan_consideration_form_ajax($form, &$form_state) {
  return $form['extra'];
}

/**
 * Consideration form submit function.
 */
function farm_plan_consideration_form_submit($form, &$form_state) {

  // Load the consideration from the form.
  $consideration = $form_state['values']['consideration'];

  // Format, sanitize, and set information from the submitted values.
  $consideration->type = $form_state['values']['type'];
  $consideration->name = check_plain($form_state['values']['name']);

  // Convert dates to timestamps.
  $consideration->start_time = strtotime($form_state['values']['start_time']);
  $consideration->end_time = strtotime($form_state['values']['end_time']);

  // If this is a new consideration, and it is specific to the plan, save the
  // plan ID.
  if (empty($consideration->id) && !empty($form_state['values']['plan']->id)) {
    $consideration->plan_id = $form_state['values']['plan']->id;
  }

  // Save the consideration.
  farm_plan_consideration_save($consideration);

  // Set a message.
  drupal_set_message(t('Consideration saved.'));

  // Redirect to the considerations list.
  $form_state['redirect'] = 'farm/plan/' . $form_state['values']['plan']->id . '/considerations';
}

/**
 * Delete confirmation form.
 *
 * @param array $form
 *   The form array.
 * @param array $form_state
 *   The form state array.
 * @param $plan
 *   The farm plan entity.
 * @param $consideration_id
 *   The ID of the consideration record.
 *
 * @return array
 *   Returns a form array.
 */
function farm_plan_consideration_delete_form(array $form, array &$form_state, $plan, $consideration_id) {

  // Store the plan in the form.
  $form['plan'] = array(
    '#type' => 'value',
    '#value' => $plan,
  );

  // Load the consideration.
  $consideration = farm_plan_consideration_load($consideration_id);

  // Store the consideration in the form.
  $form['consideration'] = array(
    '#type' => 'value',
    '#value' => $consideration,
  );

  // Build a confirmation form.
  return confirm_form($form, t('Are you sure you want to delete %name?', array(
    '%name' => $consideration->name,
  )), 'farm/plan/' . $plan->id . '/considerations', t('This action cannot be undone.'), t('Delete'), t('Cancel'));
}

/**
 * Delete form submit handler.
 *
 * @param array $form
 *   The form array.
 * @param array $form_state
 *   The form state array.
 */
function farm_plan_consideration_delete_form_submit(array $form, array &$form_state) {

  // Pull the plan and consideration out of the form.
  $plan = $form_state['values']['plan'];
  $consideration = $form_state['values']['consideration'];

  // Delete the consideration.
  farm_plan_consideration_delete($consideration->id);

  // Set a message.
  drupal_set_message(t('The consideration was deleted.'));

  // Redirect to the considerations list.
  $form_state['redirect'] = 'farm/plan/' . $plan->id . '/considerations';
}

Functions

Namesort descending Description
farm_plan_consideration_create Create a new consideration.
farm_plan_consideration_delete Delete a consideration from the database.
farm_plan_consideration_delete_form Delete confirmation form.
farm_plan_consideration_delete_form_submit Delete form submit handler.
farm_plan_consideration_form Build the farm plan considerations form.
farm_plan_consideration_form_ajax Consideration form ajax callback.
farm_plan_consideration_form_submit Consideration form submit function.
farm_plan_consideration_list Page callback for considerations list, filtered for a plan.
farm_plan_consideration_load Load a consideration from the database.
farm_plan_consideration_menu Implements hook_menu().
farm_plan_consideration_save Save a consideration to the database.
farm_plan_consideration_types Get available consideration types provided by modules.
farm_plan_farm_plan_consideration_types Implements hook_farm_plan_consideration_types().