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

Issue #3217168: View of assets in location

This commit is contained in:
Michael Stenta 2021-06-04 21:16:47 -04:00
commit b04d5eba6b
9 changed files with 219 additions and 3 deletions

View file

@ -13,6 +13,8 @@ determining an asset's location and geometry.
**Methods**:
`isLocation($asset)` - Check if an asset is a location. Returns a boolean.
`isFixed($asset)` - Check if an asset is fixed. Returns a boolean.
`hasLocation($asset)` - Check if an asset is located within other location

View file

@ -68,6 +68,9 @@ function farm_location_views_data_alter(array &$data) {
'id' => 'asset_location',
'field_name' => 'location',
],
'argument' => [
'id' => 'asset_location',
],
];
}
}

View file

@ -22,6 +22,13 @@ class AssetLocation implements AssetLocationInterface {
*/
const ASSET_FIELD_GEOMETRY = 'intrinsic_geometry';
/**
* The name of the asset boolean location field.
*
* @var string
*/
const ASSET_FIELD_LOCATION = 'is_location';
/**
* The name of the asset boolean fixed field.
*
@ -99,6 +106,13 @@ class AssetLocation implements AssetLocationInterface {
);
}
/**
* {@inheritdoc}
*/
public function isLocation(AssetInterface $asset): bool {
return !empty($asset->{static::ASSET_FIELD_LOCATION}->value);
}
/**
* {@inheritdoc}
*/

View file

@ -10,6 +10,17 @@ use Drupal\log\Entity\LogInterface;
*/
interface AssetLocationInterface {
/**
* Check if an asset is a location.
*
* @param \Drupal\asset\Entity\AssetInterface $asset
* The Asset entity.
*
* @return bool
* Returns TRUE if it is a location, FALSE otherwise.
*/
public function isLocation(AssetInterface $asset): bool;
/**
* Check if an asset is fixed.
*

View file

@ -0,0 +1,44 @@
<?php
namespace Drupal\farm_location\Plugin\views\argument;
use Drupal\views\Plugin\views\argument\ArgumentPluginBase;
/**
* An argument for filtering assets by their current location.
*
* @ingroup views_argument_handlers
*
* @ViewsArgument("asset_location")
*/
class AssetLocation extends ArgumentPluginBase {
/**
* {@inheritdoc}
*/
public function query($group_by = FALSE) {
// First query for a list of asset IDs in the location, then use this list
// to filter the current View.
// We do this in two separate queries for a few reasons:
// 1. The Drupal and Views query APIs do not support the kind of compound
// JOIN that we use in the asset.location service's getAssetsByLocation().
// 2. We need to allow other modules to override the asset.location service
// to provide their own location logic (eg: the Group asset module). They
// shouldn't have to override this Views argument handler as well.
// 3. It keeps this Views argument handler's query modifications very
// simple. It only needs the condition: "WHERE asset.id IN (:asset_ids)".
// See https://www.drupal.org/project/farm/issues/3217168 for more info.
$location = \Drupal::entityTypeManager()->getStorage('asset')->load($this->argument);
$assets = \Drupal::service('asset.location')->getAssetsByLocation($location);
$asset_ids = [];
foreach ($assets as $asset) {
$asset_ids[] = $asset->id();
}
// Filter to only include assets with those IDs.
$this->ensureMyTable();
$this->query->addWhere(0, "$this->tableAlias.id", $asset_ids, 'IN');
}
}

View file

@ -1063,7 +1063,7 @@ display:
display_plugin: rest_export
id: csv
display_title: 'CSV export (rest)'
position: 4
position: 5
display_options:
display_extenders: { }
style:
@ -1118,7 +1118,7 @@ display:
display_plugin: entity_browser
id: entity_browser
display_title: 'Entity browser'
position: 4
position: 6
display_options:
display_extenders: { }
defaults:
@ -1608,7 +1608,7 @@ display:
display_plugin: page
id: page_children
display_title: 'Children (page)'
position: 3
position: 4
display_options:
display_extenders: { }
display_description: ''
@ -1680,6 +1680,70 @@ display:
- url.query_args
- user.permissions
tags: { }
page_location:
display_plugin: page
id: page_location
display_title: 'By location (page)'
position: 3
display_options:
display_extenders: { }
display_description: ''
path: asset/%asset/assets
arguments:
location:
id: location
table: asset
field: location
relationship: none
group_type: group
admin_label: ''
default_action: empty
exception:
value: all
title_enable: false
title: All
title_enable: false
title: ''
default_argument_type: fixed
default_argument_options:
argument: ''
default_argument_skip_url: false
summary_options:
base_path: ''
count: true
items_per_page: 25
override: false
summary:
sort_order: asc
number_of_records: 0
format: default_summary
specify_validation: false
validate:
type: none
fail: 'not found'
validate_options: { }
entity_type: asset
plugin_id: asset_location
defaults:
arguments: false
menu:
type: tab
title: Assets
description: ''
expanded: false
parent: ''
weight: 50
context: '0'
menu_name: main
cache_metadata:
max-age: 0
contexts:
- 'languages:language_content'
- 'languages:language_interface'
- url
- url.query_args
- user.permissions
tags: { }
page_type:
display_plugin: page
id: page_type

View file

@ -8,3 +8,8 @@ services:
arguments: ['@entity_type.manager']
tags:
- { name: access_check, applies_to: _asset_logs_access }
farm_ui_views.location_assets_access:
class: Drupal\farm_ui_views\Access\FarmLocationAssetViewsAccessCheck
arguments: [ '@entity_type.manager', '@asset.location' ]
tags:
- { name: access_check, applies_to: _location_assets_access }

View file

@ -0,0 +1,67 @@
<?php
namespace Drupal\farm_ui_views\Access;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Routing\Access\AccessInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Access\AccessResult;
use Drupal\farm_location\AssetLocationInterface;
/**
* Checks access for displaying Views of assets in a location.
*/
class FarmLocationAssetViewsAccessCheck implements AccessInterface {
/**
* The asset storage.
*
* @var \Drupal\Core\Entity\EntityStorageInterface
*/
protected $assetStorage;
/**
* The asset location service.
*
* @var \Drupal\farm_location\AssetLocationInterface
*/
protected $assetLocation;
/**
* FarmLocationAssetViewsAccessCheck constructor.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager service.
* @param \Drupal\farm_location\AssetLocationInterface $asset_location
* The asset location service.
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager, AssetLocationInterface $asset_location) {
$this->assetStorage = $entity_type_manager->getStorage('asset');
$this->assetLocation = $asset_location;
}
/**
* A custom access check.
*
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The route match.
*/
public function access(RouteMatchInterface $route_match) {
// If there is no "asset" parameter, bail.
$asset_id = $route_match->getParameter('asset');
if (empty($asset_id)) {
return AccessResult::allowed();
}
// Allow access if the asset is a location.
/** @var \Drupal\asset\Entity\AssetInterface $asset */
$asset = $this->assetStorage->load($asset_id);
$access = AccessResult::allowedIf($this->assetLocation->isLocation($asset));
// Invalidate the access result when assets are changed.
$access->addCacheTags(["asset_list"]);
return $access;
}
}

View file

@ -21,6 +21,12 @@ class RouteSubscriber extends RouteSubscriberBase {
if ($route = $collection->get('view.farm_log.page_asset')) {
$route->setRequirement('_asset_logs_access', 'Drupal\farm_ui_views\Access\FarmAssetLogViewsAccessCheck::access');
}
// Add our _location_assets_access requirement to
// view.farm_asset.page_location.
if ($route = $collection->get('view.farm_asset.page_location')) {
$route->setRequirement('_location_assets_access', 'Drupal\farm_ui_views\Access\FarmLocationAssetViewsAccessCheck::access');
}
}
}