diff --git a/src/Plugin/EntityUsage/Track/Link.php b/src/Plugin/EntityUsage/Track/Link.php index 13f7a5a..a62b706 100644 --- a/src/Plugin/EntityUsage/Track/Link.php +++ b/src/Plugin/EntityUsage/Track/Link.php @@ -3,6 +3,7 @@ namespace Drupal\entity_usage\Plugin\EntityUsage\Track; use Drupal\Core\Entity\ContentEntityInterface; +use Drupal\Core\Entity\ContentEntityTypeInterface; use Drupal\Core\Entity\EntityFieldManagerInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\entity_usage\EntityUsage; @@ -15,7 +16,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface; * * @EntityUsageTrack( * id = "link", - * label = @Translation("Link Fields"), + * label = @Translation("Link Field References"), * description = @Translation("Tracks usage of entities related in link fields."), * ) */ @@ -87,8 +88,9 @@ class Link extends EntityUsageTrackBase { /** @var \Drupal\link\Plugin\Field\FieldType\LinkItem $field_item */ foreach ($entity->{$field_name} as $field_item) { // This item got added. Track the usage up. - $linked_entity = $this->getEntityFromLinkValue($field_item); - $this->usageService->add($linked_entity['entity_id'], $linked_entity['entity_type'], $entity->id(), $entity->getEntityTypeId(), $this->pluginId); + $target_entity = $this->getTargetEntity($field_item); + list($target_type, $target_id) = explode('|', $target_entity); + $this->usageService->add($target_id, $target_type, $entity->id(), $entity->getEntityTypeId(), $this->pluginId); } } } @@ -120,43 +122,43 @@ class Link extends EntityUsageTrackBase { } foreach ($this->linkFieldsAvailable($entity) as $field_name) { - $current_target_ids = []; + $current_targets = []; foreach ($translations as $translation) { if (!$translation->{$field_name}->isEmpty()) { foreach ($translation->{$field_name} as $field_item) { - $linked_entity = $this->getEntityFromLinkValue($field_item); - if (!empty($linked_entity['entity_type']) && !empty($linked_entity['entity_id'])) { - $current_target_ids[] = $linked_entity['entity_type'] . ':' . $linked_entity['entity_id']; + $target_entity = $this->getTargetEntity($field_item); + if ($target_entity) { + $current_targets[] = $target_entity; } } } } - $original_target_ids = []; + $original_targets = []; foreach ($originals as $original) { if (!$original->{$field_name}->isEmpty()) { foreach ($original->{$field_name} as $field_item) { - $linked_entity = $this->getEntityFromLinkValue($field_item); - if (!empty($linked_entity['entity_type']) && !empty($linked_entity['entity_id'])) { - $original_target_ids[] = $linked_entity['entity_type'] . ':' . $linked_entity['entity_id']; + $target_entity = $this->getTargetEntity($field_item); + if ($target_entity) { + $original_targets[] = $target_entity; } } } } // If more than one translation references the same target entity, we // record only one usage. - $original_target_ids = array_unique($original_target_ids); - $current_target_ids = array_unique($current_target_ids); + $original_targets = array_unique($original_targets); + $current_targets = array_unique($current_targets); - $added_ids = array_diff($current_target_ids, $original_target_ids); - $removed_ids = array_diff($original_target_ids, $current_target_ids); + $added_ids = array_diff($current_targets, $original_targets); + $removed_ids = array_diff($original_targets, $current_targets); - foreach ($added_ids as $id) { - $values = explode(":", $id); - $this->usageService->add($values[1], $values[0], $entity->id(), $entity->getEntityTypeId(), $this->pluginId); + foreach ($added_ids as $added_entity) { + list($target_type, $target_id) = explode('|', $added_entity); + $this->usageService->add($target_id, $target_type, $entity->id(), $entity->getEntityTypeId(), $this->pluginId); } - foreach ($removed_ids as $id) { - $values = explode(":", $id); - $this->usageService->delete($values[1], $values[0], $entity->id(), $entity->getEntityTypeId()); + foreach ($removed_ids as $removed_entity) { + list($target_type, $target_id) = explode('|', $removed_entity); + $this->usageService->delete($target_id, $target_type, $entity->id(), $entity->getEntityTypeId()); } } } @@ -189,8 +191,9 @@ class Link extends EntityUsageTrackBase { /** @var \Drupal\link\Plugin\Field\FieldType\LinkItem $field_item */ foreach ($translation->{$field_name} as $field_item) { // This item got deleted. Track the usage down. - $linked_entity = $this->getEntityFromLinkValue($field_item); - $this->usageService->delete($linked_entity['entity_id'], $linked_entity['entity_type'], $entity->id(), $entity->getEntityTypeId()); + $target_entity = $this->getTargetEntity($field_item); + list($target_type, $target_id) = explode('|', $target_entity); + $this->usageService->delete($target_id, $target_type, $entity->id(), $entity->getEntityTypeId()); } } } @@ -224,32 +227,33 @@ class Link extends EntityUsageTrackBase { } /** - * Get entity type and ID from a Link field uri. + * Gets the target entity of a link item. * - * @param \Drupal\link\LinkItemInterface $field_item - * The field value item. + * @param \Drupal\link\LinkItemInterface $link + * The LinkItem to get the target from. * - * @return array - * An associative array with keys: - * - entity_type: The entity type found, or NULL otherwise. - * - entity_id: The entity ID found, or NULL otherwise. + * @return string|null + * Target Type and ID glued together with a '|' or NULL if no entity linked. */ - private function getEntityFromLinkValue(LinkItemInterface $field_item) { - $return = [ - 'entity_type' => NULL, - 'entity_id' => NULL, - ]; - - $uri = !empty($field_item->uri) ? $field_item->uri : NULL; - if ($uri && strpos($uri, 'entity:') === 0) { - $values = explode("/", substr($uri, 7)); - if ($values) { - $return['entity_type'] = $values[0]; - $return['entity_id'] = $values[1]; - } + private function getTargetEntity(LinkItemInterface $link) { + // Check if LinkItem is linking to an entity. + $url = $link->getUrl(); + if (!$url->isRouted() || !preg_match('/^entity\./', $url->getRouteName())) { + return NULL; + } + + // Ge the target entity type and ID. + $route_parameters = $url->getRouteParameters(); + $target_type = array_keys($route_parameters)[0]; + $target_id = $route_parameters[$target_type]; + + if (!($this->entityTypeManager->getDefinition($target_type) instanceof ContentEntityTypeInterface)) { + // This module only supports content entity types. + return NULL; } - return $return; + // Glue the target type and ID together for easy comparison. + return $target_type . '|' . $target_id; } } diff --git a/tests/src/FunctionalJavascript/IntegrationTest.php b/tests/src/FunctionalJavascript/IntegrationTest.php index 134fd8d..0adaaa3 100644 --- a/tests/src/FunctionalJavascript/IntegrationTest.php +++ b/tests/src/FunctionalJavascript/IntegrationTest.php @@ -230,7 +230,7 @@ class IntegrationTest extends EntityUsageJavascriptTestBase { $this->assertEquals([$node2_id => '1'], $usage['link']['node']); // Delete the host and usage should be released. $node2->delete(); - $usage = $usage_service->listUsage($node1, TRUE); + $usage = $usage_service->listUsage($node1); $this->assertEquals([], $usage); }