Skip to content
Snippets Groups Projects

Issue #3316144: Field cardinality is not preserved on inheritance

1 file
+ 89
17
Compare changes
  • Side-by-side
  • Inline
+ 89
17
@@ -16,6 +16,9 @@ use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\OpenModalDialogCommand;
use Drupal\Core\Url;
use Drupal\Component\Serialization\Json;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\field_inheritance\Entity\FieldInheritanceInterface;
/**
* Implements hook_help().
@@ -45,6 +48,7 @@ function field_inheritance_entity_bundle_field_info_alter(&$fields, EntityTypeIn
$inherited_fields = \Drupal::entityTypeManager()->getStorage('field_inheritance')->loadMultiple($inherited_field_ids);
if (!empty($inherited_fields)) {
$x = 0;
/** @var \Drupal\field_inheritance\Entity\FieldInheritanceInterface $field */
foreach ($inherited_fields as $field) {
// We are only interested in adding computed fields to the destination
// entity type.
@@ -75,24 +79,13 @@ function field_inheritance_entity_bundle_field_info_alter(&$fields, EntityTypeIn
$settings['destination field'] = $field->destinationField();
}
// Grab the configuration of the source field.
$source_field = FieldConfig::loadByName($field->sourceEntityType(), $field->sourceEntityBundle(), $field->sourceField());
if (!empty($source_field)) {
$settings = array_merge($settings, $source_field->getSettings());
$type = $source_field->getType();
}
else {
// This may be a basefield.
$basefields = \Drupal::service('entity_field.manager')->getBaseFieldDefinitions($field->sourceEntityType());
if (!empty($basefields[$field->sourceField()])) {
$source_field = $basefields[$field->sourceField()];
$settings = array_merge($settings, $source_field->getSettings());
$type = $source_field->getType();
}
else {
continue;
}
$source_field = _field_inheritance_get_field_definition('source', $field);
if (!$source_field) {
continue;
}
$cardinality = _field_inheritance_determine_cardinality($field);
$settings = array_merge($settings, $source_field->getSettings());
$type = $source_field->getType();
// Set the factory class used to inherit the data from the source.
$class = '\Drupal\field_inheritance\FieldInheritanceFactory';
@@ -109,6 +102,7 @@ function field_inheritance_entity_bundle_field_info_alter(&$fields, EntityTypeIn
->setLabel(t('@label', ['@label' => $field->label()]))
->setName($field->idWithoutTypeAndBundle())
->setDescription(t('The inherited field: @field', ['@field' => $field->label()]))
->setCardinality($cardinality)
->setComputed(TRUE)
->setClass($class)
->setSettings($settings)
@@ -129,6 +123,84 @@ function field_inheritance_entity_bundle_field_info_alter(&$fields, EntityTypeIn
}
}
/**
* Get the field definition for the source or destination field.
*
* @param string $type
* The 'source' or 'destination' field.
* @param Drupal\field_inheritance\Entity\FieldInheritanceInterface $inherited_field
* The inherited field configuration.
*/
function _field_inheritance_get_field_definition(string $type, FieldInheritanceInterface $inherited_field): ?FieldDefinitionInterface {
switch ($type) {
case 'destination':
if (!$inherited_field->destinationField()) {
return NULL;
}
$field = FieldConfig::loadByName($inherited_field->destinationEntityType(), $inherited_field->destinationEntityBundle(), $inherited_field->destinationField());
if (!empty($field)) {
return $field;
}
$basefields = \Drupal::service('entity_field.manager')->getBaseFieldDefinitions($inherited_field->destinationEntityType());
return $basefields[$inherited_field->destinationField()] ?? NULL;
case 'source':
default:
if (!$inherited_field->sourceField()) {
return NULL;
}
$field = FieldConfig::loadByName($inherited_field->sourceEntityType(), $inherited_field->sourceEntityBundle(), $inherited_field->sourceField());
if (!empty($field)) {
return $field;
}
$basefields = \Drupal::service('entity_field.manager')->getBaseFieldDefinitions($inherited_field->sourceEntityType());
return $basefields[$inherited_field->sourceField()] ?? NULL;
}
}
/**
* Determine what the cardinality of the inherited field should be.
*
* @param Drupal\field_inheritance\Entity\FieldInheritanceInterface $field
* The inherited field configuration.
*/
function _field_inheritance_determine_cardinality(FieldInheritanceInterface $field): int {
$source_cardinality = $destination_cardinality = 1;
$source_field = _field_inheritance_get_field_definition('source', $field);
if ($source_field) {
$source_cardinality = $source_field->getFieldStorageDefinition()->getCardinality();
}
if ($field->destinationField()) {
$destination_field = _field_inheritance_get_field_definition('destination', $field);
if ($destination_field) {
$destination_cardinality = $destination_field->getFieldStorageDefinition()->getCardinality();
}
}
switch ($field->type()) {
case 'prepend':
case 'append':
if (in_array(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED, [$source_cardinality, $destination_cardinality])) {
return FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED;
}
return $source_cardinality + $destination_cardinality;
break;
case 'fallback':
if (in_array(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED, [$source_cardinality, $destination_cardinality])) {
return FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED;
}
return max($source_cardinality, $destination_cardinality);
case 'inherit':
default:
return $source_cardinality;
}
return 1;
}
/**
* Implements hook_form_alter().
*/
Loading