You are here

function gutenberg_entity_presave in Gutenberg 8

Same name and namespace in other branches
  1. 8.2 gutenberg.module \gutenberg_entity_presave()

Implements hook_entity_presave().

File

./gutenberg.module, line 599
Provides integration with the Gutenberg editor.

Code

function gutenberg_entity_presave($entity) {
  if (!$entity
    ->getEntityTypeId() === 'node') {
    return;
  }
  $config = \Drupal::service('config.factory')
    ->getEditable('gutenberg.settings');
  $node_type = $entity
    ->bundle();
  $gutenberg_enabled = $config
    ->get($node_type . '_enable_full');
  if (!$gutenberg_enabled) {
    return;
  }

  /*
   * DEPRECATED >>>
   * To be removed on 1.12 or 1.13 (2.0?)
   */

  // Get first text field, that's the one that'll have
  // gutenberg text format
  // TODO: We already have this on node_edit_form_alter,
  // let's move it to a function.
  $value_fields = [
    'title',
  ];
  $text_fields = [];

  // Used for media.
  $file_fields = [];

  // Iterate over all node fields and apply gutenberg text format
  // on first text field found.
  $field_names = array_keys($entity
    ->getFields());
  foreach ($field_names as $value) {
    $definition = $entity
      ->getFieldDefinition($value);
    $field_properties = $definition
      ->getFieldStorageDefinition()
      ->getPropertyDefinitions();
    if (in_array('value', array_keys($field_properties))) {
      $value_fields[] = $value;
    }

    // Check for "rich-text" fields.
    if (in_array('format', array_keys($field_properties))) {
      $text_fields[] = $value;
    }
    if (isset($field_properties['entity'])) {
      $settings = $definition
        ->getSettings();

      // Check for images/files.
      if ($settings['target_type'] === 'file') {
        $file_fields[] = $value;
      }
      if ($settings['target_type'] === 'media') {
        $file_fields[] = $value;
      }
    }
  }
  if (count($text_fields) === 0) {
    return;
  }
  $str = $entity
    ->get($text_fields[0])
    ->getString();

  // Iterate over all mapped fields and set its values.
  $mapped_fields = _gutenberg_get_mapped_fields(json_decode($config
    ->get($node_type . '_template')));
  foreach ($mapped_fields as $item) {
    $re = '/((<!-- .*?\\{.*"mappingField":"' . $item['field'] . '".*} -->)([\\s\\S]*?)(<!-- \\/[\\s\\S]*?-->|\\/-->)|(<!-- .*?\\{.*"mappingField":"' . $item['field'] . '".*} \\/-->))/m';

    // matches:
    // 0: all block
    // 1: opening block comment tag (get attributes from here)
    // 2: content
    // 3: closing block comment tag.
    preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0);

    // Get block attributes.
    $re = '/((<!-- .*?({[\\s\\S]*}).*-->)|(<!-- .*?({[\\s\\S]*}).*\\/-->))/m';
    $tag = $matches[0][2] !== '' ? $matches[0][2] : $matches[0][1];
    preg_match_all($re, $tag, $attrs, PREG_SET_ORDER, 0);
    $attributes = json_decode($attrs[0][3], TRUE);

    // Remove line breaks.
    $re = '/\\r?\\n|\\r/';
    $value = $matches[0][3];
    $value = preg_replace($re, '', $value);
    if (in_array($item['field'], $value_fields)) {
      $entity
        ->set($item['field'], strip_tags($value));
    }

    // Set text fields.
    if (in_array($item['field'], $text_fields)) {
      $entity
        ->set($item['field'], $matches[0][3]);
    }
    if (in_array($item['field'], $file_fields)) {
      $value = is_array($attributes[$item['attribute']]) ? $attributes[$item['attribute']][0] : $attributes[$item['attribute']];
      $entity
        ->set($item['field'], [
        'target_id' => $value,
      ]);
    }
  }

  /*
   * <<< DEPRECATED
   */
  $mapped_fields = _gutenberg_get_mapping_fields(json_decode($config
    ->get($node_type . '_template')));
  $re = '/((<!-- .*?\\{.*"mappingFields":.*} -->)([\\s\\S]*?)(<!-- \\/[\\s\\S]*?-->|\\/-->)|(<!-- .*?\\{.*"mappingFields":.*} \\/-->))/m';
  preg_match_all($re, $str, $blocks, PREG_SET_ORDER, 0);

  // Let's build the field's array of values.
  $fields = [];

  // For each block match.
  foreach ($blocks as $block) {

    // Get block attributes.
    $re = '/((^<!-- .*?({[\\s\\S]*}).*-->$))/m';
    $tag = $block[2] !== '' ? $block[2] : $block[1];
    preg_match_all($re, $tag, $attrs, PREG_SET_ORDER, 0);
    $attributes = json_decode($attrs[0][3], TRUE);

    // Remove line breaks from block's "inner" content.
    // $content is the "inner" content.
    $re = '/\\r?\\n|\\r/';
    $content = $block[3];
    $content = preg_replace($re, '', $content);
    foreach ($attributes['mappingFields'] as $mField) {
      if (!isset($fields[$mField['field']])) {
        $fields[$mField['field']] = [];
      }
      $value = isset($mField['attribute']) ? $attributes[$mField['attribute']] : $content;

      // Value doesn't support array yet.
      if (is_array($value)) {
        $value = $value[0];
      }
      $value = strip_tags($value);
      if (isset($mField['property'])) {
        $fields[$mField['field']][$mField['property']] = $value;
      }
      else {
        $fields[$mField['field']] = $value;
      }
    }
  }
  foreach ($fields as $key => $value) {
    try {
      $entity
        ->set($key, $value);
    } catch (\Exception $e) {
      \Drupal::logger('gutenberg')
        ->error(t('Mapping field: @message', [
        '@message' => $e
          ->getMessage(),
      ]));
    }
  }
}