You are here

farm_ui.module in farmOS 7

Farm UI module code.

File

modules/farm/farm_ui/farm_ui.module
View source
<?php

/**
 * @file
 * Farm UI module code.
 */

/**
 * Implements hook_hook_info().
 */
function farm_ui_hook_info() {
  $hooks['farm_ui_entities'] = array(
    'group' => 'farm_ui',
  );
  $hooks['farm_ui_entity_view_groups'] = array(
    'group' => 'farm_ui',
  );
  $hooks['farm_ui_entity_views'] = array(
    'group' => 'farm_ui',
  );
  $hooks['farm_ui_actions'] = array(
    'group' => 'farm_ui',
  );
  $hooks['farm_area_link_alter'] = array(
    'group' => 'farm_area',
  );
  return $hooks;
}

/**
 * Implements hook_farm_info().
 */
function farm_ui_farm_info() {

  /**
   * @todo
   * Move this out of farm_ui.
   * Currently it depends on farm_ui_entities() function, which should be moved
   * to a new general-purpose farm_entity module.
   */

  // Load information about farmOS entities.
  $entities = farm_ui_entities();

  // Define default data schemas by field type.
  // We hard-code this information because it's relatively stable, and easier
  // than trying to figure out what the RestWS module is going to produce for
  // each field type. This information is useful to clients like Field Kit.
  $field_type_schemas = array(
    'list_text' => '""',
    'file' => '{"id": null}',
    'geofield' => '{"geom": ""}',
    'image' => '{"id": null}',
    'taxonomy_term_reference' => '{"id": null}',
    'number_integer' => 'null',
    'datestamp' => 'null',
    'text_long' => '{"value": "", "format": "farm_format"}',
    'entityreference' => '{"id": null}',
    'text' => '""',
    'field_collection' => 'null',
    // See $field_collection_schemas logic below.
    'list_boolean' => 'null',
    'fraction' => 'null',
  );
  $field_type_schema_exceptions = array(
    'field_farm_data' => '""',
  );
  $field_collection_schemas = array(
    'field_farm_movement' => '{"area": [{"id": null}], "geometry": ""}',
    'field_farm_membership' => '{"group": [{"id": null}]}',
    'field_farm_quantity' => '{"measure": "", "value": null, "unit": {"id": null}, "label": ""}',
    'field_farm_inventory' => '{"asset": {"id": null}, "value": null}',
    'field_farm_animal_tag' => '{"id": "", "location": "", "type": ""}',
  );

  // Add information about entity type bundles.
  $info = array();
  foreach ($entities as $entity_type => $bundles) {
    foreach ($bundles as $bundle => $bundle_info) {

      // Only copy certain information, since some things are farmOS internals
      // that have no purpose in external API surface.
      $fields = array(
        'label',
        'label_plural',
      );
      foreach ($fields as $field) {
        $info['resources'][$entity_type][$bundle][$field] = $bundle_info[$field];
      }

      // Load the fields on this bundle and some basic information about them:
      // label, required, type, and data schema information.

      /**
       * @todo
       * This is removing the `field_farm_` prefix, so that it is consistent
       * with the prefix handling in farm_api.module.
       */
      $fields = field_info_instances($entity_type, $bundle);
      foreach ($fields as $field_instance) {
        $field = field_info_field($field_instance['field_name']);
        $field_info = array(
          'label' => $field_instance['label'],
          'type' => $field['type'],
          'required' => $field_instance['required'],
        );

        /**
         * @deprecated
         * The 'default_value' is not reliable, and will be removed from farmOS
         * in 7.x-1.5.
         */
        if (array_key_exists('default_value', $field_instance)) {
          $field_info['default_value'] = $field_instance['default_value'];
        }
        if (array_key_exists($field['type'], $field_type_schemas)) {
          $data_schema = $field_type_schemas[$field['type']];
          if (array_key_exists($field_instance['field_name'], $field_type_schema_exceptions)) {
            $data_schema = $field_type_schema_exceptions[$field_instance['field_name']];
          }
          if ($field['type'] == 'field_collection' && array_key_exists($field_instance['field_name'], $field_collection_schemas)) {
            $data_schema = $field_collection_schemas[$field_instance['field_name']];
          }
          if (isset($field['cardinality']) && $field['cardinality'] != 1) {
            $data_schema = '[' . $data_schema . ']';
          }
          $field_info['data_schema'] = drupal_json_decode($data_schema);
        }
        $field_name = str_replace('field_farm_', '', $field_instance['field_name']);
        $info['resources'][$entity_type][$bundle]['fields'][$field_name] = $field_info;
      }
    }
  }

  // Add vocabulary IDs to taxonomy_term bundles.
  $vocabs = taxonomy_vocabulary_get_names();
  foreach ($vocabs as $vocab) {
    if (!empty($info['resources']['taxonomy_term'][$vocab->machine_name])) {
      $info['resources']['taxonomy_term'][$vocab->machine_name]['vid'] = $vocab->vid;
    }
  }

  // Return the farm info.
  return $info;
}

/**
 * Implements hook_menu_alter().
 */
function farm_ui_menu_alter(&$items) {

  // This function adds links to "All assets", "All logs", and "All plans" in
  // the Farm menu. In order to do that, we need to make sure that this hook
  // runs after the Views module's implementation of hook_menu_alter(). That is
  // accomplished via hook_module_implements_alter() below.
  // Replicate the farm/assets menu item to farm/assets/all.
  if (!empty($items['farm/assets'])) {
    $items['farm/assets/all'] = $items['farm/assets'];
    $items['farm/assets/all']['title'] = t('All assets');
    $items['farm/assets/all']['weight'] = -100;
  }

  // Replicate the farm/logs menu item to farm/logs/all.
  if (!empty($items['farm/logs'])) {
    $items['farm/logs/all'] = $items['farm/logs'];
    $items['farm/logs/all']['title'] = t('All logs');
    $items['farm/logs/all']['weight'] = -100;
  }

  // Replicate the farm/plans menu item to farm/plans/all.
  if (!empty($items['farm/plans'])) {
    $items['farm/plans/all'] = $items['farm/plans'];
    $items['farm/plans/all']['title'] = t('All plans');
    $items['farm/plans/all']['weight'] = -100;
  }
}

/**
 * Implements hook_module_implements_alter().
 */
function farm_ui_module_implements_alter(&$implementations, $hook) {

  // Ensure that this module's hook_menu_alter() runs last.
  // This is necessary for hook_menu_alter() above.
  if ($hook == 'menu_alter') {
    $group = $implementations['farm_ui'];
    unset($implementations['farm_ui']);
    $implementations['farm_ui'] = $group;
  }
}

/**
 * Implements hook_entity_view().
 */
function farm_ui_entity_view($entity, $type, $view_mode, $langcode) {

  // If the view mode is not 'full', bail.
  if ($view_mode != 'full') {
    return;
  }

  // We are only concerned with asset, plan, log, and term entities.
  $entity_types = array(
    'farm_asset',
    'farm_plan',
    'log',
    'taxonomy_term',
  );
  if (!in_array($type, $entity_types)) {
    return;
  }

  // Determine the bundle based on the type.
  switch ($type) {
    case 'farm_asset':
    case 'farm_plan':
    case 'log':
      $bundle = $entity->type;
      break;
    case 'taxonomy_term':
      $bundle = $entity->vocabulary_machine_name;
      break;
  }

  // Set the entity breadcrumb.
  module_load_include('inc', 'farm_ui', 'farm_ui.breadcrumb');
  farm_ui_entity_set_breadcrumb($type, $bundle);

  // Add Views to the entity.
  module_load_include('inc', 'farm_ui', 'farm_ui.entity_views');
  $views = farm_ui_entity_views($type, $bundle, $entity);
  if (!empty($views)) {
    $entity->content['views'] = $views;
    $entity->content['views']['#weight'] = 100;
  }
}

/**
 * Implements hook_menu_breadcrumb_alter().
 */
function farm_ui_menu_breadcrumb_alter(&$active_trail, $item) {

  // Use helper function to alter the breadcrumb.
  module_load_include('inc', 'farm_ui', 'farm_ui.breadcrumb');
  _farm_ui_menu_breadcrumb_alter($active_trail, $item);
}

/**
 * Implements hook_menu_local_tasks_alter().
 */
function farm_ui_menu_local_tasks_alter(&$data, $router_item, $root_path) {

  // Use helper function to add farmOS action links.
  module_load_include('inc', 'farm_ui', 'farm_ui.action_links');
  _farm_ui_menu_local_tasks_alter($data, $router_item, $root_path);
}

/**
 * Implements hook_views_post_render().
 */
function farm_ui_views_post_render(&$view, &$output, &$cache) {

  // Use helper function to add asset cluster maps to Views.
  module_load_include('inc', 'farm_ui', 'farm_ui.views');
  _farm_ui_views_post_render($view, $output, $cache);
}

/**
 * Implements hook_entityreference_view_widget_views_arguments_alter().
 */
function farm_ui_entityreference_view_widget_views_arguments_alter(&$arguments, $form_state, $view) {

  // Use helper function to alter arguments.
  module_load_include('inc', 'farm_ui', 'farm_ui.views');
  _farm_ui_entityreference_view_widget_views_arguments_alter($arguments, $form_state, $view);
}

/**
 * Load farmOS entity UI information.
 *
 * @param string $type
 *   Optionally specify the entity type.
 * @param string $bundle
 *   Optionally specify the entity bundle.
 *
 * @return array
 *   Returns an array of entity UI information.
 */
function farm_ui_entities($type = '', $bundle = '') {

  // Ask modules for entity UI information and static cache the results.
  $entity_info =& drupal_static(__FUNCTION__);
  if (!isset($entity_info)) {
    $entity_info = module_invoke_all('farm_ui_entities');
  }

  // If a type and bundle are specified, return specific info.
  if (!empty($type) && !empty($bundle)) {
    $bundle_info = array();
    if (!empty($entity_info[$type][$bundle])) {
      $bundle_info = $entity_info[$type][$bundle];
    }
    return $bundle_info;
  }

  // Return the entity UI information.
  return $entity_info;
}

/**
 * Helper function for getting the path to a View's page display.
 *
 * @param string $view_name
 *   The machine name of the View.
 * @param string $display
 *   The machine name of the page display (defaults to "page").
 *
 * @return string
 *   Returns the path to a View's page display.
 */
function farm_ui_view_page_path($view_name, $display = 'page') {

  // Load the View.
  $view = views_get_view($view_name);

  // If the page display exists and has a path, return it.
  if (!empty($view->display[$display]->display_options['path'])) {
    return $view->display[$display]->display_options['path'];
  }

  // Otherwise, return an empty string.
  return '';
}

/**
 * Encapsulates logic for figuring out where the area ID argument is in a View.
 *
 * Views of assets should always have an area ID as their first contextual
 * filter.
 *
 * Views of logs are a bit more complicated. Most logs apply to assets, so they
 * have an asset ID contextual filter first, and an area ID contextual filter
 * second. However, some logs do not apply to assets, so the first contextual
 * filter is the area ID.
 *
 * This function will use information provided by hook_farm_ui_entities() to
 * determine the position of the area ID argument. In general, it will return
 * 1 (the first argument position). If the entity type is 'log', and the log
 * type does not apply to assets, then it will return 2 (second argument).
 *
 * @param $type
 *   The entity type.
 * @param $bundle
 *   The entity bundle.
 *
 * @return int
 *   Returns the position of the area ID argument as an integer.
 */
function farm_ui_views_area_argument_position($type, $bundle) {

  // Load entity UI information.
  $ui_info = farm_ui_entities($type, $bundle);

  // Default the area ID argument position to 1.
  $arg = 1;

  // If this is a log entity that applies to assets, the argument position
  // should be 2.
  if ($type == 'log' && (empty($ui_info['farm_asset']) || $ui_info['farm_asset'] != 'none')) {
    $arg = 2;
  }

  // Return the argument position.
  return $arg;
}