3
0
Fork 0
mirror of https://github.com/farmOS/farmOS.git synced 2024-02-23 11:37:38 +01:00
farmOS/modules/ui/views/farm_ui_views.module

362 lines
12 KiB
PHP
Raw Normal View History

<?php
/**
* @file
2020-11-27 16:33:30 +01:00
* The farmOS UI Views module.
*/
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\views\ViewExecutable;
use Drupal\views\Views;
/**
* Implements hook_entity_type_build().
*/
function farm_ui_views_entity_type_build(array &$entity_types) {
/** @var \Drupal\Core\Entity\EntityTypeInterface[] $entity_types */
// Override the "collection" link path for assets, logs, and plans to use
// the Views provided by this module.
$collection_paths = [
'asset' => '/assets',
'log' => '/logs',
'plan' => '/plans',
];
foreach ($collection_paths as $entity_type => $path) {
if (!empty($entity_types[$entity_type])) {
$entity_types[$entity_type]->setLinkTemplate('collection', $path);
}
}
}
/**
* Implements hook_farm_dashboard_panes().
*/
2020-11-27 16:33:30 +01:00
function farm_ui_views_farm_dashboard_panes() {
$panes = [];
// If the plan module is enabled, add active plans pane.
if (\Drupal::service('module_handler')->moduleExists('plan')) {
$panes['active_plans'] = [
'view' => 'farm_plan',
'view_display_id' => 'block_active',
'group' => 'plans',
'weight' => 0,
];
}
// Add upcoming and late logs panes.
$panes['upcoming_tasks'] = [
'view' => 'farm_log',
'view_display_id' => 'block_upcoming',
'group' => 'logs',
'weight' => 10,
];
$panes['late_tasks'] = [
'view' => 'farm_log',
'view_display_id' => 'block_late',
'group' => 'logs',
'weight' => 11,
];
return $panes;
}
/**
* Implements hook_entity_base_field_info_alter().
*/
function farm_ui_views_entity_base_field_info_alter(&$fields, EntityTypeInterface $entity_type) {
// Use Entity Browser widget for certain asset reference fields.
$alter_fields = [
'log' => [
'asset',
],
'quantity' => [
'inventory_asset',
],
];
foreach ($alter_fields as $entity_type_id => $field_names) {
if ($entity_type->id() != $entity_type_id) {
continue;
}
foreach ($field_names as $field_name) {
if (!empty($fields[$field_name])) {
/** @var \Drupal\Core\Field\BaseFieldDefinition[] $fields */
$form_display_options = $fields[$field_name]->getDisplayOptions('form');
$form_display_options['type'] = 'entity_browser_entity_reference';
$form_display_options['settings'] = [
'entity_browser' => 'farm_asset',
'field_widget_display' => 'label',
'field_widget_remove' => TRUE,
'open' => TRUE,
'selection_mode' => 'selection_append',
'field_widget_edit' => FALSE,
'field_widget_replace' => FALSE,
'field_widget_display_settings' => [],
];
$fields[$field_name]->setDisplayOptions('form', $form_display_options);
}
}
}
}
/**
* Implements hook_views_pre_view().
*/
function farm_ui_views_views_pre_view(ViewExecutable $view, $display_id, array &$args) {
// We only want to alter the Views we provide.
2021-03-08 15:52:40 +01:00
if (!in_array($view->id(), ['farm_asset', 'farm_log', 'farm_plan', 'farm_quantity'])) {
return;
}
// If this is a "By type" display, alter the fields and filters.
$bundle = FALSE;
if ($display_id == 'page_type' && !empty($args[0])) {
$bundle = $args[0];
}
elseif ($view->id() == 'farm_log' && $display_id == 'page_asset' && !empty($args[1]) && $args[1] != 'all') {
$bundle = $args[1];
}
if (!empty($bundle)) {
// Remove the type field and filter handlers.
$view->removeHandler($display_id, 'field', 'type');
$view->removeHandler($display_id, 'filter', 'type');
// If the entity type has a bundle_plugin manager, add all of its
// bundle fields and filters to the page_type view.
if (\Drupal::entityTypeManager()->hasHandler($view->getBaseEntityType()->id(), 'bundle_plugin')) {
farm_ui_views_add_bundle_handlers($view, $display_id, $bundle, 'field');
farm_ui_views_add_bundle_handlers($view, $display_id, $bundle, 'filter');
}
}
// If this is the "Upcoming" or "Late" Logs block display, add a "more" link
// that points to the default page display with appropriate filters.
if ($view->id() == 'farm_log' && in_array($display_id, ['block_upcoming', 'block_late'])) {
$view->display_handler->setOption('use_more', TRUE);
$view->display_handler->setOption('use_more_always', TRUE);
$view->display_handler->setOption('link_display', 'custom_url');
$today = date('Y-m-d', \Drupal::time()->getRequestTime());
if ($display_id == 'block_upcoming') {
$view->display_handler->setOption('use_more_text', t('View all upcoming logs'));
$view->display_handler->setOption('link_url', 'logs?status[]=pending&start=' . $today);
}
elseif ($display_id == 'block_late') {
$view->display_handler->setOption('use_more_text', t('View all late logs'));
$view->display_handler->setOption('link_url', 'logs?status[]=pending&end=' . $today);
}
}
}
/**
* Helper function for adding bundle-specific field and filter handlers.
*
* @param \Drupal\views\ViewExecutable $view
* The View to add handlers to.
* @param string $display_id
* The ID of the View display to add handlers to.
* @param string $bundle
* The bundle name.
* @param string $type
* The handler type ('field' or 'filter').
*/
function farm_ui_views_add_bundle_handlers(ViewExecutable $view, string $display_id, string $bundle, string $type) {
// Get the entity and bundle.
$base_entity = $view->getBaseEntityType();
/** @var \Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */
$table_mapping = \Drupal::entityTypeManager()->getStorage($base_entity->id())->getTableMapping();
// Load bundle fields.
/** @var \Drupal\entity\BundleFieldDefinition[] $bundle_fields */
$bundle_fields = \Drupal::entityTypeManager()->getHandler($base_entity->id(), 'bundle_plugin')->getFieldDefinitions($bundle);
foreach (array_reverse($bundle_fields) as $field_name => $field_definition) {
// Skip the bundle field if the view display was set as "hidden".
$view_options = $field_definition->getDisplayOptions('view');
if (empty($view_options) || (!empty($view_options['region']) && $view_options['region'] == 'hidden')) {
continue;
}
// Save the field type.
$field_type = $field_definition->getType();
// Get the field's table column (main property name).
$table = $table_mapping->getFieldTableName($field_name);
$property_name = $field_definition->getFieldStorageDefinition()->getMainPropertyName();
// Build the column and table names.
$column_name = $field_name . '_' . $property_name;
$views_option_name = $table . '.' . $column_name;
// Add a field handler if a views data field definition exists.
if ($type == 'field') {
$field_options = Views::viewsDataHelper()->fetchFields($table, 'field');
if (isset($field_options[$views_option_name])) {
// Build field options for the field type.
$field_options = [];
switch ($field_type) {
case 'entity_reference':
$target_type = $field_definition->getSetting('target_type');
// Do not render a link to referenced taxonomy terms.
if ($target_type === 'taxonomy_term') {
$field_options['type'] = 'entity_reference_label';
$field_options['settings']['link'] = FALSE;
}
break;
case 'timestamp':
// Render timestamp fields in the html_date format.
$field_options['type'] = 'timestamp';
$field_options['settings']['date_format'] = 'html_date';
break;
}
// Add the field handler.
$new_field_id = $view->addHandler($display_id, 'field', $table, $column_name, $field_options);
// Determine what position to insert the field handler.
switch ($base_entity->id()) {
case 'asset':
case 'plan':
$sort_field = 'name';
break;
case 'log':
$sort_field = 'quantity_target_id';
break;
case 'quantity':
default:
$sort_field = FALSE;
break;
}
// Sort the field handlers if necessary.
if (!empty($sort_field)) {
farm_ui_views_sort_field($view, $display_id, $new_field_id, $sort_field);
}
}
}
// Add a filter handler if a views data filter definition exists.
elseif ($type == 'filter') {
$filter_options = Views::viewsDataHelper()->fetchFields($table, 'filter');
if (isset($filter_options[$views_option_name])) {
$filter_options = [
'id' => $field_name,
'table' => $table,
'field' => $column_name,
'exposed' => TRUE,
'expose' => [
'operator_id' => $column_name . '_op',
'label' => $filter_options[$views_option_name]['title'],
'identifier' => $column_name,
'multiple' => TRUE,
],
'entity_type' => $base_entity->id(),
'entity_field' => $field_name,
];
// Build filter options for the field type.
switch ($field_type) {
case 'entity_reference':
$target_type = $field_definition->getSetting('target_type');
// Use a select widget for taxonomy term references.
if ($target_type === 'taxonomy_term') {
$filter_options['type'] = 'select';
// Limit to specific vocabularies if configured.
$handler_settings = $field_definition->getSetting('handler_settings');
$filter_options['limit'] = FALSE;
if (!empty($handler_settings['target_bundles'])) {
$filter_options['limit'] = TRUE;
$filter_options['vid'] = reset($handler_settings['target_bundles']);
}
}
break;
case 'string':
// String fields use the contains operator.
$filter_options['operator'] = 'contains';
break;
}
// Add the filter handler.
$view->addHandler($display_id, 'filter', $table, $column_name, $filter_options);
}
}
}
}
/**
* Helper function for sorting a field handler.
*
* Based off the \Drupal\views_ui\Form\Ajax\Rearrange.php method of ordering
* handlers in views.
*
* @param \Drupal\views\ViewExecutable $view
* The View to add handlers to.
* @param string $display_id
* The ID of the View display to add handlers to.
* @param string $field_id
* The ID of the field to sort.
* @param string $base_field_id
* The ID of an existing field in the View. The field defined by $field_id
* will be added after this field in the View.
*/
function farm_ui_views_sort_field(ViewExecutable $view, string $display_id, string $field_id, string $base_field_id) {
// Get the existing field handlers.
$type = 'field';
$types = ViewExecutable::getHandlerTypes();
$display = $view->displayHandlers->get($display_id);
$field_handlers = $display->getOption($types[$type]['plural']);
// Define the new field handler and insert at desired position.
$new_field_handler = [$field_id => $field_handlers[$field_id]];
$keys = array_keys($field_handlers);
$index = array_search($base_field_id, $keys, TRUE);
$pos = empty($index) ? count($field_handlers) : $index + 1;
$new_field_handlers = array_merge(array_slice($field_handlers, 0, $pos, TRUE), $new_field_handler, array_slice($field_handlers, $pos, NULL, TRUE));
// Set the display to use the sorted field handlers.
$display->setOption($types[$type]['plural'], $new_field_handlers);
}
/**
* Implements hook_views_pre_render().
*/
function farm_ui_views_views_pre_render(ViewExecutable $view) {
// We only want to alter the Views we provide.
2021-03-08 15:52:40 +01:00
if (!in_array($view->id(), ['farm_asset', 'farm_log', 'farm_plan', 'farm_quantity'])) {
return;
}
// If this is a "By type" display and a bundle argument is specified, load
// the bundle label and set the title.
$bundle = FALSE;
if ($view->current_display == 'page_type' && !empty($view->args[0])) {
$bundle = $view->args[0];
}
elseif ($view->id() == 'farm_log' && $view->current_display == 'page_asset' && !empty($view->args[1]) && $view->args[1] != 'all') {
$bundle = $view->args[1];
}
if (!empty($bundle)) {
$bundles = \Drupal::service('entity_type.bundle.info')->getBundleInfo($view->getBaseEntityType()->id());
if (!empty($bundles[$bundle])) {
$view->setTitle($bundles[$bundle]['label'] . ' ' . $view->getBaseEntityType()->getPluralLabel());
}
}
}