Drupal 8.x

I would like to alter the value of all/any ckeditor/text fields on a node.

Currently working with HOOK_node_presave().

Ideally, I'd like an agnostic approach that doesn't mind where the field is coming from, e.g. paragraph, node, taxonomy, etc.

How can I loop through all fields, check the field type, get and replace the value?


MYMODULE.module

Working with the below code gets me close I think:

use Drupal\Core\Entity\EntityInterface;

function MYMODULE_node_presave(EntityInterface $entity) {
  $fieldsArray = \Drupal::service('entity_field.manager')->getFieldMapByFieldType('text_long');

  foreach($fieldsArray as $longTextName=>$key) {

    kpr($key); // This returns an array of the values I need.
    if ($entity->hasField($key)) {
      $entity->get($result)->value = preg_replace(
        $toReplace,
        $replaceWith,
        $entity->get($result)->value
      );
    }
  }

}

Try #2;

use Drupal\Core\Field\FieldConfigInterface;

function hash_tag_make_node_presave($node) {
  // Call helper function to get all the fields
  $fieldsArray = getContentTypeFields($node->bundle());
  //- Loop through fields 
  foreach ($fieldsArray as $fieldName => $fieldConfig) {
    // Check if text_long exists on node
    if ($fieldConfig->getType() == 'text_long') {
      $node->get($fieldName)->value = preg_replace(
        $toReplace,
        $replaceWith,
        $entity->get($fieldName)->value
      );
    }
    // Check if text_long exists on paragraph
    if ($fieldConfig->getType() == 'entity_reference_revisions') {
      $paragraphs = $node->get($fieldName);
      foreach ($paragraphs as $paragraph => $item) {
        // Can get value by "field_name"
        kpr($item->entity->get('field_paragraph_full_html')->value);
        // But want to get by $fieldName above
        if (??? == 'text_long') {
          // Preg replace code.
        }
      }
    }
  }
  exit;
}

/**
 * Helper function to Get all fields of content type:
 *
 * @param $contentType
 *
 * @return array
 */
function getContentTypeFields($contentType) {
  $entityManager = Drupal::service('entity.manager');
  $fields = [];
  if (!empty($contentType)) {
    $fields = array_filter(
      $entityManager->getFieldDefinitions('node', $contentType), function ($field_definition) {
      return $field_definition instanceof FieldConfigInterface;
    }
    );
  }

  return $fields;
}
  • In general this code looks like it belongs in a text filter. For the agnostic way on a field type basis you could extend the field widget of this field type. – 4k4 Nov 8 at 9:45
  • Could you expand a bit on the "looks like it belongs in a text filter"? Not sure I follow and would like to... – Prestosaurus Nov 8 at 20:26
  • Create a custom text filter and add it to the text format(s) used in the field. – 4k4 Nov 8 at 21:22
  • That is definitely a viable option using the text filters. Not the path for me currently, but a good Drupal way to do it. Great thinking! – Prestosaurus Nov 9 at 20:58

You can use FieldConfigInterface to get fields info.
Try the following:

use Drupal\Core\Field\FieldConfigInterface;

function MYMODULE_node_presave($node) {
  //- Call helper function to get all the fields
  $fieldsArray = getContentTypeFields($node->bundle());
  //- Loop through fields 
  foreach ($fieldsArray as $fieldName => $fieldConfig) {
    ///- Example to check if type is text_with_summary
    if ($fieldConfig->getType() == 'text_with_summary') {
      /**
       * @TODO : Something here for field of type text_with_summary
       */
    }
  }
}

/**
 * Helper function to Get all fields of content type:
 *
 * @param $contentType
 *
 * @return array
 */
function getContentTypeFields($contentType) {
  $entityManager = Drupal::service('entity.manager');
  $fields = [];
  if (!empty($contentType)) {
    $fields = array_filter(
      $entityManager->getFieldDefinitions('node', $contentType), function ($field_definition) {
      return $field_definition instanceof FieldConfigInterface;
    }
    );
  }

  return $fields;
}
  • This works well for node, yet it does not return fields from paragraph, comment, etc. – Prestosaurus Nov 8 at 16:39
  • you are welcome you can adjust the function on your needs. i thought that you need only for nodes. – berramou Nov 8 at 17:01
  • I've been working with your answer, and have had some success, but just can't seem to accomplish the final step. Above code may be a little messy right now but feels close. I think maybe if this works for node and paragraph, it could easily for comment fields, etc. Right now I am just using the single helper function. – Prestosaurus yesterday

Your Answer

 
discard

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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