Problem/Motivation
It would be convenient if GroupMembershipInterface::getGroupMembers
returned an array of assets keyed by their ID. The current implementation does not specify what the array keys will be and actually behaves differently depending on if $recurse
is specified.
The relevant code is here: https://github.com/farmOS/farmOS/blob/30f70615b949291f04d29ea78c4007d2a6...
....
/** @var \Drupal\asset\Entity\AssetInterface[] $assets */
$assets = $this->entityTypeManager->getStorage('asset')->loadMultiple($asset_ids);
if ($recurse) {
// Iterate through the assets to check if any of them are groups.
$groups = array_filter($assets, function (AssetInterface $asset) {
return $asset->bundle() === 'group';
});
$assets = array_merge($assets, $this->getGroupMembers($groups));
}
return $assets;
When $recurse = FALSE
we return EntityStorageInterface::loadMultiple
directly:
/**
* Loads one or more entities.
*
* @param $ids
* An array of entity IDs, or NULL to load all entities.
*
* @return \Drupal\Core\Entity\EntityInterface[]
* An array of entity objects indexed by their IDs. Returns an empty array
* if no matching entities are found.
*/
public function loadMultiple(array $ids = NULL);
When $recurse = TRUE
(the default value) we always return the result of array_merge which *appends* the values of all numeric keys. This always results in an array starting at index 0.
Returning an array of assets keyed by the asset ID is preferable. One example is that it makes it easier to build an options array required for checkbox/select form elements using array_map
:
// Get group members.
$group_members = $this->groupMembership->getGroupMembers($groups, TRUE);
// Build group options.
$group_options = array_map(function (AssetInterface $asset) {
return $asset->label();
}, $group_members);
natsort($group_options);
$form['group'] = [
'#type' => 'select',
'#title' => $this->t('Group'),
'#options' => $group_options,
];
Steps to reproduce
N/A
Proposed resolution
Update GroupMembershipInterface::getGroupMembers
to always return an array of assets keyed by asset ID.
The technical "fix" for this one implementation is simple - change array_merge to use array_replace instead.
Remaining tasks
- Determine if we want to make this change. Challenges maintaining this going forward?
- Determine if we should make this same change anywhere else?
- Add/update tests to ensure asset IDs are returned as the keys, with both
$recurse
options.
User interface changes
None.
API changes
Update/clarify the expected array keys from GroupMembershipInterface::getGroupMembers
Data model changes
None.
Comments
Comment #2
paul121 CreditAttribution: paul121 commentedComment #3
m.stentaMakes sense to me!
Location (and maybe Inventory?) are the only other places that come to mind... not sure if they need something similar. But that can be done in a separate issue IMO.
Comment #4
paul121 CreditAttribution: paul121 commentedhttps://github.com/farmOS/farmOS/pull/494
Comment #5
m.stentaLGTM!
I took a quick look at these and I don't think any changes are needed. The
AssetLocation::getAssetsByLocation()
method simply returns the result of$this->entityTypeManager->getStorage('asset')->loadMultiple($asset_ids)
, so it will be keyed by asset ID.And there is no similar code in the inventory logic that I can see.
Comment #7
m.stenta