Issue #3243383: Allow flags to be limited to specific entity types and bundles
This commit is contained in:
parent
95bedca516
commit
97309754c1
|
@ -94,7 +94,7 @@ function mymodule_farm_entity_bundle_field_info(EntityTypeInterface $entity_type
|
|||
Certain fields on assets and logs include a list of options to select from.
|
||||
These include:
|
||||
|
||||
- **Flags** (on assets and logs)
|
||||
- **Flags** (on assets, logs, and plans)
|
||||
- Monitor (`monitor`)
|
||||
- Needs review (`needs_review`)
|
||||
- Priority (`priority`)
|
||||
|
@ -142,16 +142,41 @@ dependencies:
|
|||
- my_module
|
||||
id: monitor
|
||||
label: Monitor
|
||||
entity_types: null
|
||||
```
|
||||
|
||||
The most important parts are the `id`, which is a unique machine name for
|
||||
the flag, and `label`, which is the human readable/translatable label that
|
||||
will be shown in the select field and other parts of the UI.
|
||||
the flag, `label`, which is the human readable/translatable label that will be
|
||||
shown in the select field and other parts of the UI, and `entity_types`, which
|
||||
can optionally specify the entity types and bundles that this flag applies to.
|
||||
|
||||
The `langcode` and `status` and `dependencies` are standard configuration
|
||||
entity properties. By putting the module's name in "enforced modules" it will
|
||||
ensure that the flag is removed when the module is uninstalled.
|
||||
|
||||
Flags can be limited to certain entity types and bundles via an optional
|
||||
`entity_types` property. This accepts a set of entity types with arrays of
|
||||
bundles that the flag applies to (or `all` to apply to all bundles). For
|
||||
example, to create a flag that only applies to Animal assets:
|
||||
|
||||
```yaml
|
||||
entity_types:
|
||||
asset:
|
||||
- animal
|
||||
```
|
||||
|
||||
To create a flag that applies to all asset types and log types, but not plans,
|
||||
specify `all` for the `asset` and `log` bundles, but omit the `plan` entity
|
||||
type:
|
||||
|
||||
```yaml
|
||||
entity_types:
|
||||
asset:
|
||||
- all
|
||||
log:
|
||||
- all
|
||||
```
|
||||
|
||||
#### Land type
|
||||
|
||||
The "Land" module in farmOS provides a "Field" type like this:
|
||||
|
@ -205,9 +230,9 @@ label: Soil test
|
|||
|
||||
#### ID tag type
|
||||
|
||||
ID tag types are similar to Flags, in that they have an `id` and `label`, but
|
||||
they also have an additional property: `bundle`. This allows the tag type to
|
||||
be limited to certain types of assets.
|
||||
ID tag types are similar to Flags, in that they have an `id` and `label`. They
|
||||
also have an additional `bundle` property, which allows them to be limited to
|
||||
certain types of assets.
|
||||
|
||||
For example, an "Ear tag" type, provided by the "Animal asset" module, only
|
||||
applies to "Animal" assets:
|
||||
|
|
|
@ -6,3 +6,4 @@ dependencies:
|
|||
- farm_flag
|
||||
id: monitor
|
||||
label: Monitor
|
||||
entity_types: null
|
||||
|
|
|
@ -6,3 +6,4 @@ dependencies:
|
|||
- farm_flag
|
||||
id: priority
|
||||
label: Priority
|
||||
entity_types: null
|
||||
|
|
|
@ -6,3 +6,4 @@ dependencies:
|
|||
- farm_flag
|
||||
id: review
|
||||
label: Needs review
|
||||
entity_types: null
|
||||
|
|
|
@ -9,3 +9,13 @@ farm_flag.flag.*:
|
|||
label:
|
||||
type: label
|
||||
label: 'Label'
|
||||
entity_types:
|
||||
type: sequence
|
||||
label: 'Entity types'
|
||||
nullable: true
|
||||
sequence:
|
||||
type: sequence
|
||||
label: 'Entity type'
|
||||
sequence:
|
||||
type: string
|
||||
label: 'Bundle'
|
||||
|
|
|
@ -5,7 +5,10 @@
|
|||
* The farmOS Flags module.
|
||||
*/
|
||||
|
||||
use Drupal\Core\Entity\ContentEntityInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Field\FieldDefinitionInterface;
|
||||
use Drupal\farm_flag\Entity\FarmFlagInterface;
|
||||
use Drupal\farm_flag\Form\EntityFlagActionForm;
|
||||
use Drupal\farm_flag\Routing\EntityFlagActionRouteProvider;
|
||||
|
||||
|
@ -37,19 +40,72 @@ function farm_flag_entity_base_field_info(EntityTypeInterface $entity_type) {
|
|||
/**
|
||||
* Allowed values callback function for the flags field.
|
||||
*
|
||||
* @param \Drupal\Core\Field\FieldDefinitionInterface $definition
|
||||
* The field definition.
|
||||
* @param \Drupal\Core\Entity\ContentEntityInterface|null $entity
|
||||
* The entity being created if applicable.
|
||||
*
|
||||
* @return array
|
||||
* Returns an array of allowed values for use in form select options.
|
||||
*/
|
||||
function farm_flag_field_allowed_values() {
|
||||
function farm_flag_field_allowed_values(FieldDefinitionInterface $definition, ContentEntityInterface $entity = NULL) {
|
||||
/** @var \Drupal\farm_flag\Entity\FarmFlagInterface[] $flags */
|
||||
$flags = \Drupal::entityTypeManager()->getStorage('flag')->loadMultiple();
|
||||
$allowed_values = [];
|
||||
$entity_type = NULL;
|
||||
$bundle = NULL;
|
||||
if (!empty($entity)) {
|
||||
$entity_type = $entity->getEntityTypeId();
|
||||
$bundle = $entity->bundle();
|
||||
}
|
||||
foreach ($flags as $id => $flag) {
|
||||
$allowed_values[$id] = $flag->getLabel();
|
||||
if (farm_flag_applies($flag, $entity_type, $bundle)) {
|
||||
$allowed_values[$id] = $flag->getLabel();
|
||||
}
|
||||
}
|
||||
return $allowed_values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if a flag applies to an entity type + bundle.
|
||||
*
|
||||
* @param \Drupal\farm_flag\Entity\FarmFlagInterface $flag
|
||||
* The flag object.
|
||||
* @param string|null $entity_type
|
||||
* The entity type machine name.
|
||||
* @param string|null $bundle
|
||||
* The bundle name.
|
||||
*
|
||||
* @return bool
|
||||
* Returns TRUE if the flag applies, FALSE otherwise.
|
||||
*/
|
||||
function farm_flag_applies(FarmFlagInterface $flag, $entity_type = NULL, $bundle = NULL) {
|
||||
|
||||
// If no entity type is specified, we assume the flag applies. This ensures
|
||||
// it shows in lists/filters where the entity type may not be known.
|
||||
if (empty($entity_type)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Load applicable entity types.
|
||||
$entity_types = $flag->getEntityTypes();
|
||||
|
||||
// The flag applies if there are no allowed entity types specified.
|
||||
if (empty($entity_types)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// The flag applies if the entity type is in the list of applicable entity
|
||||
// types, and the bundle is in the list of applicable bundles (or the flag
|
||||
// applies to "all" bundles).
|
||||
if (array_key_exists($entity_type, $entity_types) && (in_array($bundle, $entity_types[$entity_type]) || in_array('all', $entity_types[$entity_type]))) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Otherwise, assume the flag does not apply.
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_theme().
|
||||
*/
|
||||
|
|
|
@ -22,6 +22,7 @@ use Drupal\Core\Config\Entity\ConfigEntityBase;
|
|||
* config_export = {
|
||||
* "id",
|
||||
* "label",
|
||||
* "entity_types",
|
||||
* },
|
||||
* )
|
||||
*
|
||||
|
@ -43,6 +44,13 @@ class FarmFlag extends ConfigEntityBase implements FarmFlagInterface {
|
|||
*/
|
||||
protected $label;
|
||||
|
||||
/**
|
||||
* The entity types and bundles that this flag applies to.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $entity_types;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -50,4 +58,11 @@ class FarmFlag extends ConfigEntityBase implements FarmFlagInterface {
|
|||
return $this->label;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getEntitytypes() {
|
||||
return $this->entity_types;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,4 +19,13 @@ interface FarmFlagInterface extends ConfigEntityInterface {
|
|||
*/
|
||||
public function getLabel();
|
||||
|
||||
/**
|
||||
* Returns the entity types and bundles that this flag applies to.
|
||||
*
|
||||
* @return array
|
||||
* An array of arrays, keyed by entity type machine name, listing bundles
|
||||
* (or `all`) that this flag applies to.
|
||||
*/
|
||||
public function getEntityTypes();
|
||||
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Drupal\farm_flag\Form;
|
||||
|
||||
use Drupal\Core\Entity\EntityFieldManagerInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Form\ConfirmFormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
@ -33,6 +34,13 @@ class EntityFlagActionForm extends ConfirmFormBase {
|
|||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* The entity field manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityFieldManagerInterface
|
||||
*/
|
||||
protected $entityFieldManager;
|
||||
|
||||
/**
|
||||
* The current user.
|
||||
*
|
||||
|
@ -68,12 +76,15 @@ class EntityFlagActionForm extends ConfirmFormBase {
|
|||
* The tempstore factory.
|
||||
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
|
||||
* The entity type manager.
|
||||
* @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager
|
||||
* The entity field manager.
|
||||
* @param \Drupal\Core\Session\AccountInterface $user
|
||||
* The current user.
|
||||
*/
|
||||
public function __construct(PrivateTempStoreFactory $temp_store_factory, EntityTypeManagerInterface $entity_type_manager, AccountInterface $user) {
|
||||
public function __construct(PrivateTempStoreFactory $temp_store_factory, EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager, AccountInterface $user) {
|
||||
$this->tempStore = $temp_store_factory->get('entity_flag_confirm');
|
||||
$this->entityTypeManager = $entity_type_manager;
|
||||
$this->entityFieldManager = $entity_field_manager;
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
|
@ -84,6 +95,7 @@ class EntityFlagActionForm extends ConfirmFormBase {
|
|||
return new static(
|
||||
$container->get('tempstore.private'),
|
||||
$container->get('entity_type.manager'),
|
||||
$container->get('entity_field.manager'),
|
||||
$container->get('current_user')
|
||||
);
|
||||
}
|
||||
|
@ -146,11 +158,28 @@ class EntityFlagActionForm extends ConfirmFormBase {
|
|||
->toString());
|
||||
}
|
||||
|
||||
// Get allowed values for the selected entities.
|
||||
// We find the intersection of all the allowed values to ensure that
|
||||
// disallowed flags cannot be assigned.
|
||||
$allowed_values = [];
|
||||
$base_field_definitions = $this->entityFieldManager->getBaseFieldDefinitions($entity_type_id);
|
||||
if (!empty($base_field_definitions['flag'])) {
|
||||
foreach ($this->entities as $entity) {
|
||||
$entity_allowed_values = farm_flag_field_allowed_values($base_field_definitions['flag'], $entity);
|
||||
if (empty($allowed_values)) {
|
||||
$allowed_values = $entity_allowed_values;
|
||||
}
|
||||
else {
|
||||
$allowed_values = array_intersect_assoc($allowed_values, $entity_allowed_values);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$form['flags'] = [
|
||||
'#type' => 'select',
|
||||
'#title' => $this->t('Flag'),
|
||||
'#description' => $this->t('Select the flags that should be attached to the record(s).'),
|
||||
'#options' => farm_flag_field_allowed_values(),
|
||||
'#options' => $allowed_values,
|
||||
'#multiple' => TRUE,
|
||||
];
|
||||
|
||||
|
|
Loading…
Reference in New Issue