/** * Initializes field values. * * @param \Drupal\Core\Entity\ContentEntityInterface $entity * An entity object. * @param array $values * (optional) An associative array of initial field values keyed by field * name. If none is provided default values will be applied. * @param array $field_names * (optional) An associative array of field names to be initialized. If none * is provided all fields will be initialized. */ protected function initFieldValues(ContentEntityInterface $entity, array $values = [], array $field_names = []) { // Populate field values. foreach ($entity as $name => $field) { if (!$field_names || isset($field_names[$name])) { if (isset($values[$name])) { $entity->{$name} = $values[$name]; } elseif (!array_key_exists($name, $values)) { $entity->get($name)->applyDefaultValue(); } } unset($values[$name]); } // Set any passed values for non-defined fields also. foreach ($values as $name => $value) { $entity->{$name} = $value; } // Make sure modules can alter field initial values. $this->invokeHook('field_values_init', $entity); }
/** * Extracts translatable data from an entity. * * @param \Drupal\Core\Entity\ContentEntityInterface $entity * The entity to get the translatable data from. * * @return array $data * Translatable data. */ public function extractTranslatableData(ContentEntityInterface $entity) { // @todo Expand this list or find a better solution to exclude fields like // content_translation_source. $field_definitions = $entity->getFieldDefinitions(); $exclude_field_types = ['language']; $translatable_fields = array_filter($field_definitions, function (FieldDefinitionInterface $field_definition) use($exclude_field_types) { return $field_definition->isTranslatable() && !in_array($field_definition->getType(), $exclude_field_types); }); $data = array(); foreach ($translatable_fields as $key => $field_definition) { $field = $entity->get($key); foreach ($field as $index => $field_item) { $format = NULL; $translatable_properties = 0; /* @var FieldItemInterface $field_item */ foreach ($field_item->getProperties() as $property_key => $property) { // Ignore computed values. $property_definition = $property->getDataDefinition(); // Ignore values that are not primitives. if (!$property instanceof PrimitiveInterface) { continue; } $translate = TRUE; // Ignore properties with limited allowed values or if they're not strings. if ($property instanceof OptionsProviderInterface || !$property instanceof StringInterface) { $translate = FALSE; } // All the labels are here, to make sure we don't have empty labels in // the UI because of no data. if ($translate == TRUE) { $data[$key]['#label'] = $field_definition->getLabel(); if (count($field) > 1) { // More than one item, add a label for the delta. $data[$key][$index]['#label'] = t('Delta #@delta', array('@delta' => $index)); } } $data[$key][$index][$property_key] = array('#label' => $property_definition->getLabel(), '#text' => $property->getValue(), '#translate' => $translate); $translatable_properties += (int) $translate; if ($translate && $field_item->getFieldDefinition()->getFieldStorageDefinition()->getSetting('max_length') != 0) { $data[$key][$index][$property_key]['#max_length'] = $field_item->getFieldDefinition()->getFieldStorageDefinition()->getSetting('max_length'); } if ($property_definition->getDataType() == 'filter_format') { $format = $property->getValue(); } } // Add the format to the translatable properties. if (!empty($format)) { foreach ($data[$key][$index] as $name => $value) { if (is_array($value) && isset($value['#translate']) && $value['#translate'] == TRUE) { $data[$key][$index][$name]['#format'] = $format; } } } // If there is only one translatable property, remove the label for it. if ($translatable_properties <= 1) { foreach (Element::children($data[$key][$index]) as $property_key) { unset($data[$key][$index][$property_key]['#label']); } } } } $embeddable_fields = $this->getEmbeddableFields($entity); foreach ($embeddable_fields as $key => $field_definition) { $field = $entity->get($key); foreach ($field as $index => $field_item) { /* @var FieldItemInterface $field_item */ foreach ($field_item->getProperties(TRUE) as $property_key => $property) { // If the property is a content entity reference and it's value is // defined, than we call this method again to get all the data. if ($property instanceof EntityReference && $property->getValue() instanceof ContentEntityInterface) { // All the labels are here, to make sure we don't have empty // labels in the UI because of no data. $data[$key]['#label'] = $field_definition->getLabel(); if (count($field) > 1) { // More than one item, add a label for the delta. $data[$key][$index]['#label'] = t('Delta #@delta', array('@delta' => $index)); } $data[$key][$index][$property_key] = $this->extractTranslatableData($property->getValue()); } } } } return $data; }
/** * {@inheritdoc} */ public function getEntityReferenceTargetIds(ContentEntityInterface $entity, $field_name, $sort = FALSE) { $target_ids = []; if ($entity->hasField($field_name)) { $field_values = $entity->get($field_name)->getValue(); foreach ($field_values as $field_value) { $target_ids[] = $field_value['target_id']; } } if ($sort) { asort($target_ids); } return $target_ids; }
/** * @param string $correspondingFieldName * Name of the field on the target entity which holds references back to the * referer that need corresponding. * @param $refererId * Id of the referencing entity whose update has triggered this. * @param $referencedEntity * The referenced entity that needs its corresponding field updating. */ public function removeCorrespondingReference($correspondingFieldName, $refererId, ContentEntityInterface $referencedEntity) { $correspondingField = $referencedEntity->get($correspondingFieldName); $currentReferences = $correspondingField->getValue(); $desiredReferences = $this->nested_array_diff([['target_id' => $refererId]], $currentReferences); $correspondingField->setValue($desiredReferences); $referencedEntity->save(); }