Ändern des Inhaltstyps eines Knotens

8

In Drupal 7 kann ich den Inhaltstyp eines Knotens mithilfe der Knotenkonvertierung problemlos ändern . Node Convert wurde jedoch weder auf Drupal 8 portiert , noch scheint es viel Begeisterung für den Port zu geben.

Wie kann ich in Drupal 8 einen Knoten von einem Inhaltstyp in einen anderen konvertieren, wenn ich zwei Inhaltstypen mit identischen Feldern habe? Welchen Code sollte ich für Drupal 8 verwenden, der dem folgenden Drupal 7-Code entspricht, der vom Node-Konvertierungsmodul verwendet wird? (Siehe node_convert_node_convert()in node_convert.util.inc .)

  // $nid, $destination_node_type, $source_fields, $destination_fields,
  // $no_fields_flag, and $hook_options are the parameters passed to the function.

  $node = node_load($nid);
  if ($node == FALSE) {
    return FALSE;
  }

  // Change the node type in the DB
  db_update('node')->fields(array('type' => $destination_node_type))->condition('nid', $nid)->execute();

  // If there are fields that can be converted
  if ($no_fields_flag == FALSE) {

    // Conversion process for each field
    $re_save_body_field = FALSE;

    // Use node revisions to extract all field revision in node_convert_field_convert
    $node_revisions = node_revision_list($node);

    foreach ($source_fields as $key => $field) {
      $replaced_body = node_convert_field_convert($node, $field, $destination_fields[$key], $destination_node_type, $node_revisions);
      if ($replaced_body == REPLACE_BODY) {
        $re_save_body_field = TRUE;
      }
    }
    // If something was appended to the body, or replaced the body, we update body field.
    if ($re_save_body_field == TRUE) {
      $field_body = field_info_fields();
      $field_body = $field_body['body'];
      $field_ids = array($field_body['id'] => $field_body['id']);
      module_invoke($field_body['storage']['module'], 'field_storage_write', 'node', $node, FIELD_STORAGE_UPDATE, $field_ids);
    }
  }

  // Omissis.

  // Clear the node cache, so we have the latest information when saving the
  // node.
  $controller = entity_get_controller('node');
  /* @var $controller DrupalEntityControllerInterface */
  $controller->resetCache(array($node->nid));
  cache_clear_all('field:node:' . $node->nid, 'cache_field');

 

node_convert_field_convert() enthält den folgenden Code.

  // &$node, $source_field, $destination_field, $destination_node_type,
  // and $node_revisions are the parameters passed to node_convert_field_convert().

  $field_info_source = field_info_fields(); // Get source field information
  $field_info_source = $field_info_source[$source_field];
  $db_info_source = $field_info_source['storage']; // Get DB specific source field information

  if ($destination_field == 'discard') {
    // Delete node info in the separate field table
    node_convert_invoke_field_storage_delete($field_info_source, $db_info_source, $node);
    return NULL;
  }

  $field_info_destination = array();
  $db_info_destination = array();
  if (!in_array($destination_field, array('discard', APPEND_TO_BODY, REPLACE_BODY))) {
    $field_info_destination = field_info_fields($destination_field); // Get destination field information
    $field_info_destination = $field_info_destination[$destination_field]; // Get destination field information
    $db_info_destination = $field_info_destination['storage']; // Get DB specific destination field information
  }

  // We save each field value from the DB for transfer. (this only applies to the current revision of the field)
  $source_values = field_get_items('node', $node, $source_field);

  if (count($node_revisions) > 1 && !in_array($destination_field, array(APPEND_TO_BODY, REPLACE_BODY))) {
    // Get all field revisions for current node
    $field_revision_values = array();
    $field_revision_source_table = current(array_keys($db_info_source['details']['sql']['FIELD_LOAD_REVISION']));
    $field_revision_destination_table = current(array_keys($db_info_destination['details']['sql']['FIELD_LOAD_REVISION']));

    $source_columns = array('entity_type', 'entity_id', 'revision_id', 'bundle', 'delta', 'language');
    foreach ($field_info_source['columns'] as $column => $attributes) {
      $source_columns[] = _field_sql_storage_columnname($source_field, $column);
    }

    $revision_query = db_select($field_revision_source_table, 'r', array('fetch' => PDO::FETCH_ASSOC))
      ->condition('entity_type', 'node')
      ->condition('bundle', $node->type)
      ->condition('entity_id', $node->nid)
      ->condition('revision_id', $node->vid, '<>')
      ->fields('r', $source_columns)->execute();

    // Change the bundle to the destination type of the node
    foreach ($revision_query as $row) {
      $row['bundle'] = $destination_node_type;
      $field_revision_values[] = $row;
    }

    // Remove all field revisions for current field in DB
    node_convert_invoke_field_storage_delete($field_info_source, $db_info_source, $node);

    // Reinsert the field revisions in the destination field revision table
    $query = db_insert($field_revision_destination_table);
    $columns = array('entity_type', 'entity_id', 'revision_id', 'bundle', 'delta', 'language');
    foreach ($field_info_destination['columns'] as $column => $attributes) {
      $columns[] = _field_sql_storage_columnname($destination_field, $column);
    }
    $query->fields($columns);
    foreach ($field_revision_values as $row) {
      $query->values(array_values($row));
    }
    $query->execute();

  }
  else {
    // After getting the source field values, we delete the values stored in the DB (this deletes values for all field revisions)
    node_convert_invoke_field_storage_delete($field_info_source, $db_info_source, $node);
  }

  // The source field value should be appended to the body or replaced.
  if ($destination_field == APPEND_TO_BODY || $destination_field == REPLACE_BODY) {
    static $node_body = '';
    //static $node_teaser = '';

    // We try to get the node body from a static variable, which means we did some body manipulations, otherwise load it.
    if (empty($node_body)) {
      $node_body_field = field_get_items('node', $node, 'body');
      $node_body = $node_body_field[0]['value'];
      //$node_teaser = $node_body_field[0]['summary'];
    }

    // Double check we have values in the field.
    if (is_array($source_values)) {
      // Get the field value.
      $field_value = node_convert_format_field_value($node, $field_info_source, TRUE);

      if ($destination_field == APPEND_TO_BODY) {
        $node_body = $node_body . "\n" . $field_value;
        //$node_teaser = $node_teaser . "\n" . $field_value['value'];
      }
      elseif ($destination_field == REPLACE_BODY) {
        $node_body = $field_value;
        //$node_teaser = $field_value['value'];
      }
      $lang_code = field_language('node', $node, $source_field);
      $node->body[$lang_code][0]['value'] = $node_body;
      //$node->body[$lang_code][0]['summary'] = $node_teaser;
    }

    return REPLACE_BODY;
  }

  // We put each field value back into the DB
  // To do it we first get the id of the field, then we find its language code from the source value
  // We add $source_values into the node object, and invoke field_storage write
  $field_ids = array($field_info_destination['id'] => $field_info_destination['id']);
  $lang_code = field_language('node', $node, $source_field);

  // Make sure that we actually have values in the source field
  if ($source_values !== FALSE) {
    $node->{$destination_field}[$lang_code] = $source_values;
  }
  else {
    $node->{$destination_field} = array();
  }

  // Give possibility to fields to pre-process their data
  // (e.g., Link module transforms attribute array into a serialized array before insertion)
  field_attach_presave('node', $node);
  // For some reason link_field_presave doesn't exist anymore, so we have to call it the processing function used inside manually.
  if ($field_info_destination['type'] == 'link_field') {
    $instances = field_info_instances('node', $destination_node_type);
    link_field_update('node', $node, $field_info_destination, $instances[$destination_field], $lang_code, $node->{$destination_field}[$lang_code]);
  }
Screenack
quelle
1
Sie haben im Grunde den größten Teil des Moduls hier gepostet und darum gebeten, dass die Konvertierung für Sie durchgeführt wird. Warum nicht eine Drupal 8-Version versuchen und dann hier spezifischere Fragen stellen, wenn Sie nicht weiterkommen?
Benjamin
Jemand anderes schlug vor, den Code aus dem D7-Modul zu veröffentlichen, um meine ursprüngliche Frage zu verbessern. Ich würde es gerne versuchen, aber ich bin dadurch eingeschränkt, dass ich kein Programmierer bin.
Screenack
2
Fair genug, jemand könnte eines Tages darauf stoßen und es portieren. Ich sehe, Sie haben das Drupal 8-Problem kommentiert, das könnte Interesse wecken. Andernfalls könnten Sie möglicherweise jemanden bezahlen, der es konvertiert. Ich glaube nicht, dass es sehr lange dauern würde.
Benjamin

Antworten:

2

Einige Zeit ist vergangen und die gute Nachricht ist, dass es jetzt das convert_bundles- Modul für d8 gibt.

Es ist Alpha, aber ich konnte es verwenden, um Entitäten auf einer Entwicklungssite zu konvertieren.

dnebrich
quelle
1

Joachim Noreiko hat gerade einen Blog-Beitrag über das Ändern des Knotentyps gepostet . Sie müssen die folgenden Tabellen aktualisieren:

  • die Entitätsbasistabelle
  • die Entitätsdatentabelle
  • die Entitätsrevisionsdatentabelle
  • jede Felddatentabelle
  • jede Felddaten-Revisionstabelle

Der Beitrag enthält vollständige Anweisungen und Codefragmente. Befolgen Sie diese einfach Schritt für Schritt.

Wim Mostrey
quelle
0

Hier ist eine Lösung zum Konvertieren von Artikelknoten in einen Blogtyp. Ich habe versucht, Bundles zu konvertieren, die in einer anderen Antwort vorgeschlagen wurden, konnte jedoch nicht filtern, welche Knoten konvertiert werden sollen. Auf diese Weise können Sie der Abfrage zusätzliche Bedingungen hinzufügen, z. B. einen Taxonomiebegriffswert.

$query = \Drupal::entityQuery('node')
  ->condition('type', 'article')
$results = $query->execute();

foreach ($results as $nid) {
  $node = \Drupal\node\Entity\Node::load($nid);
  $node->set('type', 'blog');
  $node->save();
}
mortona42
quelle