class EntityParser in Entity Share 8.3
Entity parser.
@package Drupal\entity_share_diff\Service
Hierarchy
- class \Drupal\entity_share_diff\Service\EntityParser implements EntityParserInterface
Expanded class hierarchy of EntityParser
1 string reference to 'EntityParser'
- entity_share_diff.services.yml in modules/
entity_share_diff/ entity_share_diff.services.yml - modules/entity_share_diff/entity_share_diff.services.yml
1 service uses EntityParser
- entity_share_diff.entity_parser in modules/
entity_share_diff/ entity_share_diff.services.yml - Drupal\entity_share_diff\Service\EntityParser
File
- modules/
entity_share_diff/ src/ Service/ EntityParser.php, line 25
Namespace
Drupal\entity_share_diff\ServiceView source
class EntityParser implements EntityParserInterface {
/**
* The diff field builder plugin manager.
*
* @var \Drupal\entity_share_diff\DiffGenerator\DiffGeneratorPluginManager
*/
protected $diffGeneratorManager;
/**
* The language manager.
*
* @var \Drupal\Core\Language\LanguageManagerInterface
*/
protected $languageManager;
/**
* The remote manager service.
*
* @var \Drupal\entity_share_client\Service\RemoteManagerInterface
*/
protected $remoteManager;
/**
* The jsonapi helper.
*
* @var \Drupal\entity_share_client\Service\JsonapiHelperInterface
*/
protected $jsonapiHelper;
/**
* The JSON:API resource type repository.
*
* @var \Drupal\jsonapi\ResourceType\ResourceTypeRepositoryInterface
*/
protected $resourceTypeRepository;
/**
* Entity reference helper service.
*
* @var \Drupal\entity_share_client\Service\EntityReferenceHelper
*/
protected $entityReferenceHelper;
/**
* The ES Remote config entity, or FALSE if parsing a local entity.
*
* @var \Drupal\entity_share_client\Entity\RemoteInterface|null
*/
protected $remote;
/**
* Temporary array of processed entities, needed to avoid infinite loop.
*
* @var array
*/
private $processedEntities;
/**
* Class constructor.
*
* @param \Drupal\entity_share_diff\DiffGenerator\DiffGeneratorPluginManager $diff_generator_manager
* The Diff manager service.
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
* The language manager.
* @param \Drupal\entity_share_client\Service\RemoteManagerInterface $remote_manager
* The ES remote manager.
* @param \Drupal\entity_share_client\Service\JsonapiHelperInterface $jsonapi_helper
* The ES JSON:API helper.
* @param \Drupal\jsonapi\ResourceType\ResourceTypeRepositoryInterface $resource_type_repository
* The resource type repository.
* @param \Drupal\entity_share_client\Service\EntityReferenceHelper $entity_reference_helper
* The entity reference helper service.
*/
public function __construct(DiffGeneratorPluginManager $diff_generator_manager, LanguageManagerInterface $language_manager, RemoteManagerInterface $remote_manager, JsonapiHelperInterface $jsonapi_helper, ResourceTypeRepositoryInterface $resource_type_repository, EntityReferenceHelper $entity_reference_helper) {
$this->diffGeneratorManager = $diff_generator_manager;
$this->languageManager = $language_manager;
$this->remoteManager = $remote_manager;
$this->jsonapiHelper = $jsonapi_helper;
$this->resourceTypeRepository = $resource_type_repository;
$this->entityReferenceHelper = $entity_reference_helper;
$this->processedEntities = [
'local' => [],
'remote' => [],
];
}
/**
* Returns Remote entity.
*
* @return \Drupal\entity_share_client\Entity\RemoteInterface|bool
* The ES Remote entity or FALSE.
*/
public function getRemote() {
return $this->remote;
}
/**
* Sets Remote entity.
*
* @param \Drupal\entity_share_client\Entity\RemoteInterface|bool $remote
* The ES Remote entity or FALSE.
*/
public function setRemote($remote) {
$this->remote = $remote;
}
/**
* {@inheritdoc}
*/
public function prepareLocalEntity(ContentEntityInterface $entity) {
$this
->setRemote(FALSE);
return $this
->parseEntity($entity);
}
/**
* {@inheritdoc}
*/
public function prepareRemoteEntity(array $remote_data, RemoteInterface $remote) {
$this
->setRemote($remote);
$remote_entity = $this->jsonapiHelper
->extractEntity($remote_data);
return $this
->parseEntity($remote_entity, $remote_data);
}
/**
* {@inheritdoc}
*/
public function validateNeedToProcess(string $uuid, bool $remote) {
$main_key = $remote ? 'remote' : 'local';
if (!in_array($uuid, $this->processedEntities[$main_key])) {
$this->processedEntities[$main_key][] = $uuid;
return TRUE;
}
return FALSE;
}
/**
* Helper: returns JSON:API public field name of one entity's remote data.
*
* @param string $field_name
* The local Drupal field name.
* @param array $entity_json_data
* The JSON:API data for a single entity.
*
* @return string
* The public field name or an empty string if not applicable.
*/
public function getPublicFieldName(string $field_name, array $entity_json_data) {
if (empty($entity_json_data['type'])) {
return '';
}
$parsed_type = explode('--', $entity_json_data['type']);
$entity_type_id = $parsed_type[0];
$bundle = $parsed_type[1];
$resource_type = $this->resourceTypeRepository
->get($entity_type_id, $bundle);
if (!$resource_type instanceof ResourceType) {
return '';
}
if (!$resource_type
->hasField($field_name)) {
return '';
}
return $resource_type
->getPublicName($field_name);
}
/**
* {@inheritdoc}
*/
public function getRemoteChangedTime(array $remote_data) {
$changed_public_name = $this
->getPublicFieldName('changed', $remote_data);
$entity_changed_time = 0;
if ($changed_public_name && !empty($remote_data['attributes'][$changed_public_name])) {
$entity_changed_time = EntityShareUtility::convertChangedTime($remote_data['attributes'][$changed_public_name]);
}
return $entity_changed_time;
}
/**
* Parses an entity.
*
* @param \Drupal\Core\Entity\ContentEntityInterface $entity
* The Drupal entity (local or remote).
* @param array $remote_data
* Used for remote entity: entity data coming from JSON:API.
*
* @return array
* Parsed data of a field, suitable for YAML parsing.
* Associative array, keyed by labels.
* Values are strings, numbers or arrays.
*/
protected function parseEntity(ContentEntityInterface $entity, array $remote_data = NULL) {
$result = [];
$langcode = $this->languageManager
->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)
->getId();
// Load entity of current language, otherwise fields are always compared by
// their default language.
if ($entity
->hasTranslation($langcode)) {
$entity = $entity
->getTranslation($langcode);
}
$irrelevant_fields = $this
->getFieldsIrrelevantForDiff($entity);
// Loop through entity fields and transform every FieldItemList object
// into an array of strings according to field type specific settings.
/** @var \Drupal\Core\Field\FieldItemListInterface $field_items */
foreach ($entity as $item_key => $field_items) {
// Prepare remote information for reference fields, if exists.
if ($this
->getRemote()) {
$public_key = $this
->getPublicFieldName($item_key, $remote_data);
}
else {
$public_key = $item_key;
}
$remote_field_data = [];
// Determine if a field should be parsed or skipped.
// If a field is an entity reference, then eliminate it in
// case the relationship is not handleable.
switch ($this->entityReferenceHelper
->relationshipHandleable($field_items)) {
case EntityReferenceHelper::RELATIONSHIP_HANDLEABLE:
$should_parse = TRUE;
if (isset($remote_data['relationships'][$public_key])) {
$remote_field_data = $remote_data['relationships'][$public_key];
if (isset($remote_field_data['data'])) {
$remote_field_data['data'] = EntityShareUtility::prepareData($remote_field_data['data']);
}
}
break;
case EntityReferenceHelper::RELATIONSHIP_NOT_HANDLEABLE:
$should_parse = FALSE;
break;
case EntityReferenceHelper::RELATIONSHIP_NOT_ENTITY_REFERENCE:
$should_parse = !in_array($item_key, $irrelevant_fields);
break;
}
if (!$should_parse) {
continue;
}
$parsed_field = $this
->parseField($item_key, $field_items, $remote_field_data);
if ($parsed_field != NULL) {
$field_label = (string) $field_items
->getFieldDefinition()
->getLabel();
$result[$field_label] = $parsed_field;
}
}
return $result;
}
/**
* Parses a field or property of entity.
*
* @param string $item_key
* The field key (machine name).
* @param \Drupal\Core\Field\FieldItemListInterface $field_items
* Field items.
* @param array $remote_field_data
* Used for remote entity: field data coming from JSON:API.
*
* @return array
* Parsed data of a field, suitable for YAML parsing.
*/
protected function parseField(string $item_key, FieldItemListInterface $field_items, array $remote_field_data = []) {
$build = [];
$field_type = $field_items
->getFieldDefinition()
->getType();
$plugin = $this->diffGeneratorManager
->createInstanceForFieldDefinition($field_type);
if ($plugin) {
// Pass the Remote config entity to the plugin.
$remote = $this
->getRemote();
if ($remote) {
$plugin
->setRemote($remote);
}
// Let the plugin build the value.
$build = $plugin
->build($field_items, $remote_field_data);
if (!empty($build)) {
// In case of a single field, flatten the array.
$cardinality = $field_items
->getFieldDefinition()
->getFieldStorageDefinition()
->getCardinality();
if ($cardinality == 1 && is_array($build)) {
$build = current($build);
}
}
}
return $build;
}
/**
* Checks if the entity should be embedded into Diff or just listed with UUID.
*
* @param string $entity_type_id
* Entity type ID.
*
* @return bool
* Whether entity of this type is embeddable or not.
*/
public function referenceEmbeddable(string $entity_type_id) {
$embeddable_types = [
'paragraph',
'media',
];
return in_array($entity_type_id, $embeddable_types);
}
/**
* Helper: lists entity properties/fields which should not appear in Diff.
*
* @param \Drupal\Core\Entity\ContentEntityInterface $entity
* The Drupal entity (local or remote).
*
* @return string[]
* Array of entity properties/fields.
*/
protected function getFieldsIrrelevantForDiff(ContentEntityInterface $entity) {
// Entity keys.
$entity_keys = $entity
->getEntityType()
->getKeys();
// Label and language code should be displayed in the Diff.
unset($entity_keys['label']);
unset($entity_keys['langcode']);
$field_names = array_values($entity_keys);
// Revision keys.
$revision_keys = array_keys($entity
->getEntityType()
->getRevisionMetadataKeys());
$field_names = array_merge($field_names, $revision_keys);
// Other keys.
$other_keys = [
'changed',
'created',
// Related to translation.
'content_translation_source',
'content_translation_affected',
'content_translation_outdated',
'revision_translation_affected',
// Related to paragraphs.
'parent_id',
'parent_type',
'parent_field_name',
// For some reason getRevisionMetadataKeys() doesn't always return these.
'revision_timestamp',
'revision_log',
];
$field_names = array_merge($field_names, $other_keys);
return $field_names;
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
EntityParser:: |
protected | property | The diff field builder plugin manager. | |
EntityParser:: |
protected | property | Entity reference helper service. | |
EntityParser:: |
protected | property | The jsonapi helper. | |
EntityParser:: |
protected | property | The language manager. | |
EntityParser:: |
private | property | Temporary array of processed entities, needed to avoid infinite loop. | |
EntityParser:: |
protected | property | The ES Remote config entity, or FALSE if parsing a local entity. | |
EntityParser:: |
protected | property | The remote manager service. | |
EntityParser:: |
protected | property | The JSON:API resource type repository. | |
EntityParser:: |
protected | function | Helper: lists entity properties/fields which should not appear in Diff. | |
EntityParser:: |
public | function | Helper: returns JSON:API public field name of one entity's remote data. | |
EntityParser:: |
public | function | Returns Remote entity. | |
EntityParser:: |
public | function |
Gets 'changed' timestamp of remote entity, if available. Overrides EntityParserInterface:: |
|
EntityParser:: |
protected | function | Parses an entity. | |
EntityParser:: |
protected | function | Parses a field or property of entity. | |
EntityParser:: |
public | function |
Prepares entity loaded from local database. Overrides EntityParserInterface:: |
|
EntityParser:: |
public | function |
Prepares entity loaded from remote by JSON:API. Overrides EntityParserInterface:: |
|
EntityParser:: |
public | function | Checks if the entity should be embedded into Diff or just listed with UUID. | |
EntityParser:: |
public | function | Sets Remote entity. | |
EntityParser:: |
public | function |
Determines if the entity has already been processed in the Diff. Overrides EntityParserInterface:: |
|
EntityParser:: |
public | function | Class constructor. |