Finding the host node of a paragraph I'm trying to find all the absolute URLs in a site (in wysiwyg content, url fields, config) to convert them into relative URLs later via manual administration. All the URLs in question are within the same Drupal site. I've managed to use PHPMyAdmin to find and record readily-accessible entities that contain absolute urls (nodes - /node/NID/edit, menu items - /admin/structure/menu/item/MLID/edit, etc.). However, I'm having a difficult time with Paragraphs.


The id of a paragraph field row is for a specific instance of the paragraph.
Without knowledge of the field hosting the paragraph, the instance could be anywhere.
The paragraph could be nested in another paragraph.


How would one go about solving this issue? How do I find the host node of paragraphs containing an absolute link?
It might be a bit easier to use the API rather than SQL for this. I'd be tempted to load all nodes, loop through all their fields and check values that way. If you hit a paragraph field, recurse and check its fields too.

This is a very rough example function, but it should get you going:

function entityHasFieldWithAbsUrl(\Drupal\Core\Entity\ContentEntityInterface $entity, array $types) {
  foreach ($entity-&gt;getFields() as $key =&gt; $field) {
    $field_type = $field-&gt;getFieldDefinition()-&gt;getType();
    $field_settings = $field-&gt;getSettings();
    if ($field_type == 'entity_reference_revisions' &amp;&amp; $field_settings['target_type'] == 'paragraph') {
      foreach ($field as $item) {
        if ($item-&gt;entity instanceof \Drupal\paragraphs\ParagraphInterface) {
          if (entityHasFieldWithAbsUrl($item-&gt;entity, $types)) {
            return TRUE;
          }
        }
      }
    }
    elseif (in_array($field_type, $types)) {
      foreach ($field as $item) {
        // Change this to something better...
        if (strpos($item-&gt;value, 'https://www.example.com/') !== FALSE) {
          return TRUE;
        }
      }
    }
  }

  return FALSE;
}


And you'd use it something like this:

$nodes_with_abs_urls = [];
$nodes = \Drupal::entityTypeManager()-&gt;getStorage('node')-&gt;loadMultiple();
$types = ['text', 'text_long', 'text_with_summary', 'string'];
foreach ($nodes as $node) {
  if (entityHasFieldWithAbsUrl($node, $types)) {
    $nodes_with_abs_urls[] = $node-&gt;id();
  }
}


You probably need to tweak the types to suit your installation, but it should work at a basic level.