acquia_dam-1.0.0-rc1/modules/acquia_dam_integration_links/src/AssetDetector/EntityEmbedTextDetector.php
modules/acquia_dam_integration_links/src/AssetDetector/EntityEmbedTextDetector.php
<?php namespace Drupal\acquia_dam_integration_links\AssetDetector; use Drupal\Component\Utility\Html; use Drupal\Core\Entity\ContentEntityInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Field\FieldItemListInterface; /** * Detects DAM asset usage in text fields. */ final class EntityEmbedTextDetector extends AssetDetectorBase { /** * List of field types supported by this detector. * * @var string[] */ protected $supportedFieldTypes = [ 'text', 'text_long', 'text_with_summary', ]; /** * Entity type manager service. * * @var \Drupal\Core\Entity\EntityTypeManagerInterface */ protected $entityTypeManager; /** * EntityEmbedTextDetector constructor. * * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager * Entity Type manager service. */ public function __construct(EntityTypeManagerInterface $entityTypeManager) { $this->entityTypeManager = $entityTypeManager; } /** * {@inheritdoc} */ public function discoverAsset(ContentEntityInterface $entity, array $field_definitions, bool $is_title_changed): array { $supported_fields = $this->filterSupportedFields($field_definitions, $this->supportedFieldTypes); // If there are no relevant updates we still need the current value, to make // sure that we do not delete an integration link for the given entity if a // referenced asset is removed from another field type. $has_relevant_updates = $this->hasRelevantUpdates($supported_fields, $entity); $new_asset_usage = []; $old_asset_usage = []; foreach ($supported_fields as $field) { if (isset($entity->original) && $has_relevant_updates) { $old_asset_usage = array_merge($old_asset_usage, $this->parseAssetId($entity->original->get($field->getName()))); } $new_asset_usage = array_merge($new_asset_usage, $this->parseAssetId($entity->get($field->getName()))); } // It can have duplicates, asset tracker will take care of those. return [ 'asset_to_register' => $new_asset_usage, 'assets_to_remove' => $old_asset_usage, ]; } /** * Gets embedded entity uuids from text fields. * * @param \Drupal\Core\Field\FieldItemListInterface $field * Field item list. * * @return array * Array containing entity uuids. */ protected function parseEntityUuid(FieldItemListInterface $field): array { $entities = []; foreach ($field->getValue() as $value) { if (empty($value['value'])) { continue; } $text = $value['value']; if (stristr($text, '<drupal-media') === FALSE) { continue; } $dom = Html::load($text); $xpath = new \DOMXPath($dom); foreach ($xpath->query('//drupal-media[@data-entity-type="media" and @data-entity-uuid and @data-embed-code-id!=""]') as $node) { $entities[] = $node->getAttribute('data-entity-uuid'); } } return $entities; } /** * Get asset ids from text field values. * * @param \Drupal\Core\Field\FieldItemListInterface $field * Field instance. * * @return array * Array containing asset ids. * * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException */ protected function parseAssetId(FieldItemListInterface $field): array { $asset_ids = []; $media_storage = $this->entityTypeManager->getStorage('media'); foreach (array_unique($this->parseEntityUuid($field)) as $entity_uuid) { $media = $media_storage->loadByProperties(['uuid' => $entity_uuid]); if (!is_array($media)) { continue; } $media = current($media); $asset_ids[] = $media->get('acquia_dam_asset_id')->asset_id; } return $asset_ids; } }