farmOS/modules/farm/farm_ui/farm_ui.module

585 lines
17 KiB
Plaintext

<?php
/**
* @file
* Farm UI module code.
*/
/**
* 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 farm_asset, log, and taxonomy_term, entities.
$entity_types = array(
'farm_asset',
'log',
'taxonomy_term',
);
if (!in_array($type, $entity_types)) {
return;
}
// Determine the bundle based on the type.
switch ($type) {
case 'farm_asset':
case 'log':
$bundle = $entity->type;
break;
case 'taxonomy_term':
$bundle = $entity->vocabulary_machine_name;
break;
}
// Get the breadcrumb from our helper function.
$breadcrumb = farm_ui_entity_type_breadcrumb($type, $bundle);
// Add base breadcrumb items to the front.
$base = array(
l(t('Home'), '<front>'),
l(t('Farm'), 'farm'),
);
$breadcrumb = array_merge($base, $breadcrumb);
// Set the breadcrumb.
drupal_set_breadcrumb($breadcrumb);
}
/**
* Build breadcrumbs for a specific entity type and bundle.
*
* @param $type
* The entity type.
* @param $bundle
* The bundle.
*
* @return array
* Returns a breadcrumb array.
*/
function farm_ui_entity_type_breadcrumb($type, $bundle) {
// Start an empty breadcrumb array.
$breadcrumb = array();
// Load entity UI information.
$ui_info = farm_ui_entities($type, $bundle);
// Get the label (plural). Bail if it's not set.
if (empty($ui_info['label_plural'])) {
return $breadcrumb;
}
$label = $ui_info['label_plural'];
// If the entity type has a View, load the path.
if (!empty($ui_info['view'])) {
$path = farm_ui_view_page_path($ui_info['view']);
}
// If this is a farm_asset entity, add a link to the full assets list.
if ($type == 'farm_asset') {
$breadcrumb[] = l(t('Assets'), 'farm/assets');
}
// Or, if this is a log entity, add a link to the full logs list.
elseif ($type == 'log') {
$breadcrumb[] = l(t('Logs'), 'farm/logs');
}
// If this is a taxonomy_term entity, and it is linked to a specific asset
// type, add the asset breadcrumb trail (recurse into this function again).
if ($type == 'taxonomy_term' && !empty($ui_info['farm_asset'])) {
$asset_breadcrumbs = farm_ui_entity_type_breadcrumb('farm_asset', $ui_info['farm_asset']);
$breadcrumb = array_merge($asset_breadcrumbs, $breadcrumb);
}
// If a path was found, add a link to the breadcrumb. Otherwise, add a simple
// text breadcrumb.
if (!empty($path)) {
$breadcrumb[] = l($label, $path);
}
else {
$breadcrumb[] = $label;
}
// If this is a taxonomy_term entity, get the default breadcrumb and tack it
// onto the end, so we can take advantage of the structure already provided
// by the taxonomy hierarchy. Shift the first item off (home) because we've
// started a new breadcrumb from scratch.
if ($type == 'taxonomy_term') {
$default_breadcrumb = drupal_get_breadcrumb();
array_shift($default_breadcrumb);
$breadcrumb = array_merge($breadcrumb, $default_breadcrumb);
}
// Return the breadcrumb.
return $breadcrumb;
}
/**
* 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 '';
}
/**
* Define action links for farmOS.
*/
function farm_ui_actions() {
// Define default farm action links.
$actions = array(
'area' => array(
'title' => t('Add area'),
'href' => 'admin/structure/taxonomy/farm_areas/add',
'views' => array(
'farm_areas',
),
'paths' => array(
'farm',
),
'weight' => -10,
),
'asset' => array(
'title' => t('Add asset'),
'href' => 'farm/asset/add',
'paths' => array(
'farm',
'farm/assets',
),
),
'log' => array(
'title' => t('Add log'),
'href' => 'log/add',
'paths' => array(
'farm',
'farm/logs',
),
'weight' => 1,
),
'user' => array(
'title' => t('Add person'),
'href' => 'admin/people/create',
'views' => array(
'farm_people',
),
),
);
// Load entity UI information.
$ui_info = farm_ui_entities();
// Create action links for each entity type/bundle.
foreach ($ui_info as $entity_type => $bundles) {
foreach ($bundles as $bundle => $info) {
// Start with an action link on the entity listing page.
if (!empty($info['label']) && !empty($info['view'])) {
switch ($entity_type) {
case 'farm_asset':
$path = 'farm/asset/add/' . $bundle;
break;
case 'log':
$path = 'log/add/' . $bundle;
break;
case 'taxonomy_term':
$path = 'admin/structure/taxonomy/' . $bundle . '/add';
break;
}
$actions[$bundle] = array(
'title' => t('Add ' . strtolower($info['label'])),
'href' => $path,
'views' => array(
$info['view'],
),
);
}
// If the entity is a log, add an action link on asset and area pages.
if ($entity_type == 'log') {
// If 'farm_asset' is empty, or if it is set to 'all', add to all
// asset pages.
if (empty($info['farm_asset']) || $info['farm_asset'] == 'all') {
$actions[$bundle]['assets'] = array('all');
}
// Otherwise, if 'farm_asset' is not set to 'none', pass the specified
// asset through.
elseif ($info['farm_asset'] != 'none') {
$actions[$bundle]['assets'] = array($info['farm_asset']);
}
// Only add an action link on area pages if 'areas' is set to TRUE.
if (!empty($info['areas']) && $info['areas'] === TRUE) {
$actions[$bundle]['paths'] = array('taxonomy/term/%');
}
}
}
}
return $actions;
}
/**
* Implements hook_menu_local_tasks_alter().
*/
function farm_ui_menu_local_tasks_alter(&$data, $router_item, $root_path) {
// Load array of defined action links.
$actions = farm_ui_actions();
// Sort by weight.
uasort($actions, 'drupal_sort_weight');
// Add actions to farm/asset/* paths.
if ($router_item['page_callback'] == 'farm_asset_view') {
// Get the asset id from the path.
$asset_id = check_plain(arg(2));
// Iterate through the actions.
foreach ($actions as $name => $action) {
// If the list of assets types is empty, skip it.
if (empty($actions[$name]['assets'])) {
continue;
}
// If 'all' assets are not allowed...
if (!in_array('all', $actions[$name]['assets'])) {
// Load the asset.
$asset = farm_asset_load($asset_id);
// If the asset's type is not in the list of acceptable types, skip it.
if (!in_array($asset->type, $actions[$name]['assets'])) {
continue;
}
}
// Build the action link.
$link = farm_ui_action_link($actions[$name]['title'], $actions[$name]['href'], array('destination' => 'farm/asset/' . $asset_id, 'farm_asset' => $asset_id));
// Add the action link to the output.
$data['actions']['output'][] = $link;
}
}
// Add actions to Views pages.
elseif ($router_item['page_callback'] == 'views_page') {
// Iterate through the actions.
foreach ($actions as $name => $action) {
// If the list of Views is empty, skip it.
if (empty($actions[$name]['views'])) {
continue;
}
// Get the View name from the first page argument.
$view_name = reset($router_item['page_arguments']);
// If the View is not in the list of acceptable Views, skip it.
if (!in_array($view_name, $actions[$name]['views'])) {
continue;
}
// Build the action link.
$link = farm_ui_action_link($actions[$name]['title'], $actions[$name]['href'], array('destination' => $root_path));
// Add the action link to the output.
$data['actions']['output'][] = $link;
}
}
// Create a new array of actions keyed by path.
$path_actions = array();
foreach ($actions as $name => $action) {
if (!empty($action['paths'])) {
foreach ($action['paths'] as $path) {
$path_actions[$path][] = $name;
}
}
}
// Add actions depending on the root path.
if (array_key_exists($root_path, $path_actions)) {
foreach ($path_actions[$root_path] as $name) {
// Generate the action link.
$link = farm_ui_action_link($actions[$name]['title'], $actions[$name]['href'], array('destination' => $root_path));
if ($root_path == 'taxonomy/term/%' || substr($root_path, 0, 11) == 'farm/area/%') {
// Get the area id from the path.
$area_id = check_plain(arg(2));
// Load the area taxonomy term.
$term = taxonomy_term_load($area_id);
// If the taxonomy term is not a farm_area, bail.
if (empty($term->vocabulary_machine_name) || $term->vocabulary_machine_name != 'farm_areas') {
continue;
}
// Build the action link.
$link = farm_ui_action_link($actions[$name]['title'], $actions[$name]['href'], array('destination' => 'taxonomy/term/' . $area_id, 'farm_area' => $area_id));
}
// Add the action link to the output.
$data['actions']['output'][] = $link;
}
}
}
/**
* Helper function for generating an action link.
*
* @param string $title
* The title of the action link.
* @param string $href
* The href path of the action link.
* @param array $query
* An array of additional query parameters to add.
*
* @return array
* Returns an action link.
*
* @see farm_ui_menu_local_tasks_alter()
*/
function farm_ui_action_link($title, $href, $query = array()) {
$action_link = array(
'#theme' => 'menu_local_action',
'#link' => array(
'title' => $title,
'href' => $href,
'localized_options' => array(
'query' => $query,
),
),
);
return $action_link;
}
/**
* 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.
$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;
}
/**
* Implements hook_entityreference_view_widget_views_arguments_alter().
*/
function farm_ui_entityreference_view_widget_views_arguments_alter(&$arguments, $form_state, $view) {
// The farm_log module provides a View that is used for searching and
// selecting assets for the field_farm_asset entity reference field, using
// the Entity Reference View Widget module.
//
// In some cases, we want to limit what shows up in the View of assets, based
// on the log type that the field is on. For instance, a seeding should only
// be able to reference planting assets, but it still uses the general
// field_farm_asset field, which technically can reference any asset type.
//
// The Entity Reference View Widget module provides this hook to allow the
// View arguments to be altered. We implement this hook, and use information
// provided by hook_farm_ui_entities() to see if we should filter the View
// results to a specific asset type, given the current log type.
//
// The View that we use is farm_asset_entityreference_view, which has two
// contextual arguments: asset id (to filter out already-selected assets), and
// asset type. The code below only tries to set the asset type argument, and
// maintains any asset id argument that is already set.
/**
* @todo
* Note that this does NOT alter the "Asset type" exposed filter. So users
* will still see that filter, and it will still default to "- Any -". If
* the contextual filter is activated here, however, then selecting any other
* asset type with the exposed filter will return an empty result set. That's
* confusing, so perhaps we should find a way to hide that exposed filter if
* this code successfully sets a contextual filter argument.
*/
// Only apply this to the View: farm_asset_entityreference_view
if ($view->name != 'farm_asset_entityreference_view') {
return;
}
// Figure out what the log type is.
if (!empty($form_state['build_info']['args'][0]->type)) {
$log_type = $form_state['build_info']['args'][0]->type;
}
// If that failed, bail.
else {
return;
}
// Load entity UI info for this log type.
$ui_info = farm_ui_entities('log', $log_type);
// If the asset type is empty, or 'all', or 'none', then we will stop here
// because we don't want to apply any filtering.
if (empty($ui_info['farm_asset']) || in_array($ui_info['farm_asset'], array('all', 'none'))) {
return;
}
// Take the asset type specified so we can use it as a filter.
$type = $ui_info['farm_asset'];
// We need to ensure that the first argument is reserved for asset id(s). So
// if it's not set, set it to 'all'.
if (empty($arguments)) {
$arguments[0] = 'all';
}
// Add the asset type as the second argument.
$arguments[1] = $type;
}
/**
* Implements hook_farm_area_links().
*/
function farm_ui_farm_area_links($id) {
$links = array();
// Load entity UI info.
$ui_info = farm_ui_entities();
// Add area links for each asset type.
if (!empty($ui_info['farm_asset'])) {
foreach ($ui_info['farm_asset'] as $asset_type => $info) {
// If a View is not available, skip it.
if (empty($info['view'])) {
continue;
}
// Load the View and generate a preview to count rows.
$view = views_get_view($info['view']);
$view->preview('default', array($id));
// If there are no results, skip it.
if (empty($view->total_rows)) {
continue;
}
// Load the View page path.
$path = farm_ui_view_page_path($info['view']);
// Add the area ID to the end of the path as an argument.
$path .= '/' . $id;
// Build a link.
$links[] = array(
'title' => $info['label_plural'] . ': ' . $view->total_rows,
'href' => $path,
);
}
}
// Add area links for some log types.
if (!empty($ui_info['log'])) {
foreach ($ui_info['log'] as $log_type => $info) {
// Only proceed if the log type has 'areas' set to TRUE.
if (empty($info['areas']) || $info['areas'] !== TRUE) {
continue;
}
// If a View is not available, skip it.
if (empty($info['view'])) {
continue;
}
// Log View arguments are a bit more complicated than Asset Views. Most
// logs apply to assets, so have an asset contextual filter first, and an
// area contextual filter second. Some logs do not apply to assets, so
// the first contextual filter is the area ID. The pattern we follow here
// is: if the entity UI info has 'farm_asset' set to 'none', then we
// assume that 'area ID' is the first argument. Otherwise, we assume that
// 'asset ID' is the first, and 'area ID' is the second. In the case of
// area links, we only care about the 'area ID', so we set the 'asset ID'
// argument to 'all'.
if ($info['farm_asset'] == 'none') {
$args = array($id);
}
else {
$args = array('all', $id);
}
// Load the View and generate a preview to count rows.
$view = views_get_view($info['view']);
$view->preview('default', $args);
// If there are no results, skip it.
if (empty($view->total_rows)) {
continue;
}
// Build the View page path with arguments.
$path = farm_ui_view_page_path($info['view']);
foreach ($args as $arg) {
$path .= '/' . $arg;
}
// Build a link.
$links[] = array(
'title' => $info['label_plural'] . ': ' . $view->total_rows,
'href' => $path,
'weight' => 10,
);
}
}
return $links;
}