0

I have this code which I am using to get the body text from a node rewrite it with a regular expression and replace it, (I am replacing all you tube video links with embed codes)

function hook_entity_presave(Drupal\Core\Entity\EntityInterface $entity) {

  switch ($entity->bundle()) {
    case 'article':

    $node_body = $entity->get('body')->value;

    Drupal::logger('origin-body')->notice($node_body);


    $node_body_replaced = preg_replace('/(?:https:\/\/)?(?:http:\/\/)?(?:www\.)?(?:youtube\.com|youtu\.be)\/(?:watch\?v=)?(.+)/', '<iframe width="560" height="315" src="https://www.youtube.com/embed/$1" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>', $node_body);

      Drupal::logger('replaced-body')->notice($node_body_replaced);
      $body_encoded = htmlspecialchars($node_body_replaced, ENT_QUOTES, 'UTF-8');
      //$entity->body = $node_body_replaced;
      $entity->set( 'body',$body_encoded  ); // This appears to be where special characters are getting escaped
      
     break;
  }
}

Both my logger messages show normal text output in the drupal log so I guess it happens somwhere when the node gets saved or $entity->set(). I have tried running through htmlspecialchars() and it does nothing.

For example, I am migrating content from WordPress and after running through this function my normal HTML becomes

<p>lorem ipsum dolar lorem ipsum dolar lorem ipsum dolar lorem ipsum dolar lorem ipsum dolar lorem ipsum dolar .</p> <!-- /wp:paragraph -->

I am using Drupal 9

0
1

Assuming by my normal HTML becomes you mean the escaped HTML is rendering on the front end, you're probably just resetting the format for the body field with this line

$entity->set('body', $body_encoded);

You can target the value directly instead like this (and you shouldn't need to encode/decode anything):

$entity->body->value = preg_replace('/(?:https:\/\/)?(?:http:\/\/)?(?:www\.)?(?:youtube\.com|youtu\.be)\/(?:watch\?v=)?(.+)/', '<iframe width="560" height="315" src="https://www.youtube.com/embed/$1" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>', $node_body);

If that isn't working you can try setting the format too:

// Possibly change 'full_html' to whatever's appropriate for your site.
$entity->body->format = 'full_html'; 

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.