Drupal 7では、 Node convert を使用してノードのコンテンツタイプを簡単に切り替えることができます。ただし、Node Convert、ただし 移植されていません からDrupal 8、また、移植に対する熱意があまりないようです。
同じフィールドを持つ2つのコンテンツタイプがある場合、ノードをコンテンツタイプから別のコンテンツタイプに変換するにはどうすればよいですかDrupal 8?Drupal 8、これは次のDrupal 7Node convertモジュールで使用されるコード)と同等ですか? ( node_convert.util.inc のnode_convert_node_convert()
を参照してください。)
_ // $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()
には、次のコードが含まれています。
_ // &$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]);
}
_
しばらく時間が経過し、d8の convert_bundles モジュールが追加されました。
これはアルファ版ですが、開発サイトでエンティティを変換するために使用することができました。
Joachim Noreikoが ノードのタイプの変更 に関するブログ投稿を投稿しました。次のテーブルを更新する必要があります。
投稿には完全な手順とコードスニペットが付属しています。
以下は、記事ノードをブログタイプに変換するためのソリューションです。別の回答で提案されているConvert Bundlesを試しましたが、変換するノードをフィルターできませんでした。これにより、分類用語の値などの条件をクエリに追加できます。
$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();
}