/** * Check if a field on the entity type to update is a possible destination field. * * @todo Should this be on our FieldManager service? * * @param \Drupal\Core\Field\FieldStorageDefinitionInterface $definition * Field definition on entity type to update to check. * @param \Drupal\Core\Field\FieldDefinitionInterface $source_field * Source field to check compatibility against. If none then check generally. * * @return bool */ protected function isDestinationFieldCompatible(FieldStorageDefinitionInterface $definition, FieldDefinitionInterface $source_field = NULL) { // @todo Create field definition wrapper class to treat FieldDefinitionInterface and FieldStorageDefinitionInterface the same. if ($definition instanceof BaseFieldDefinition && $definition->isReadOnly()) { return FALSE; } // Don't allow updates on updates! if ($definition->getType() == 'entity_reference') { if ($definition->getSetting('target_type') == 'scheduled_update') { return FALSE; } } if ($source_field) { $matching_types = $this->getMatchingFieldTypes($source_field->getType()); if (!in_array($definition->getType(), $matching_types)) { return FALSE; } // Check cardinality $destination_cardinality = $definition->getCardinality(); $source_cardinality = $source_field->getFieldStorageDefinition()->getCardinality(); // $destination_cardinality is unlimited. It doesn't matter what source is. if ($destination_cardinality != -1) { if ($source_cardinality == -1) { return FALSE; } if ($source_cardinality > $destination_cardinality) { return FALSE; } } switch ($definition->getType()) { case 'entity_reference': // Entity reference field must match entity target types. if ($definition->getSetting('target_type') != $source_field->getSetting('target_type')) { return FALSE; } // @todo Check bundles break; // @todo Other type specific conditions? } } return TRUE; }
/** * Creates a new field definition based upon a field storage definition. * * In cases where one needs a field storage definitions to act like full * field definitions, this creates a new field definition based upon the * (limited) information available. That way it is possible to use the field * definition in places where a full field definition is required; e.g., with * widgets or formatters. * * @param \Drupal\Core\Field\FieldStorageDefinitionInterface $definition * The field storage definition to base the new field definition upon. * * @return $this */ public static function createFromFieldStorageDefinition(FieldStorageDefinitionInterface $definition) { return static::create($definition->getType())->setCardinality($definition->getCardinality())->setConstraints($definition->getConstraints())->setCustomStorage($definition->hasCustomStorage())->setDescription($definition->getDescription())->setLabel($definition->getLabel())->setName($definition->getName())->setProvider($definition->getProvider())->setQueryable($definition->isQueryable())->setRequired($definition->isRequired())->setRevisionable($definition->isRevisionable())->setSettings($definition->getSettings())->setTargetEntityTypeId($definition->getTargetEntityTypeId())->setTranslatable($definition->isTranslatable()); }
/** * Create a form display for a newly clone field. * * This function attempts to use same setting settings as the source field. * * @param \Drupal\scheduled_updates\ScheduledUpdateTypeInterface $scheduled_update_type * @param $field_name * @param $field_config_id * @param $entity_type * @param $definition * Source field definition * @param $new_field_name */ protected function createFormDisplay(ScheduledUpdateTypeInterface $scheduled_update_type, $field_config_id, FieldStorageDefinitionInterface $definition, $new_field_name) { $destination_bundle = $scheduled_update_type->id(); $field_name = $definition->getName(); $entity_type = $scheduled_update_type->getUpdateEntityType(); /** @var EntityFormDisplay $destination_form_display */ $destination_form_display = EntityFormDisplay::load("scheduled_update.$destination_bundle.default"); if (empty($destination_form_display)) { $destination_form_display = EntityFormDisplay::create([ 'targetEntityType' => 'scheduled_update', 'bundle' => $destination_bundle, 'mode' => 'default', 'status' => TRUE, ]); } $display_options = []; if ($field_config_id) { $parts = explode('.', $field_config_id); $source_bundle = $parts[1]; /** @var EntityFormDisplay $source_form_display */ $source_form_display = EntityFormDisplay::load("$entity_type.$source_bundle.default"); $display_options = $source_form_display->getComponent($field_name); } else { if ($definition instanceof BaseFieldDefinition) { $display_options = $definition->getDisplayOptions('form'); if (empty($display_options)) { if ($definition->getType()) { // Provide default display for base boolean fields that don't have their own form display $display_options = [ 'type' => 'boolean_checkbox', 'settings' => ['display_label' => TRUE], ]; } } } } if (empty($display_options)) { $display_options = []; } if ($destination_form_display) { $destination_form_display->setComponent($new_field_name, $display_options); $destination_form_display->save(); } else { // Alert user if display options could not be created. // @todo Create default display options even none on source. drupal_set_message( $this->t( 'Form display options could not be created for @field they will have to be created manually.', ['@field' => $field_name] ), 'warning'); } }