Trong Drupal 7, tôi có thể dễ dàng chuyển đổi loại nội dung của nút bằng cách sử dụng chuyển đổi Node . Node Convert, tuy nhiên, đã không được chuyển sang Drupal 8, và dường như không có nhiều sự nhiệt tình cho cổng.
Nếu tôi có hai loại nội dung với các trường giống nhau, làm cách nào tôi có thể chuyển đổi một nút từ loại nội dung sang loại khác, trong Drupal 8? Mã tôi nên sử dụng cho Drupal 8 là gì, tương đương với mã Drupal 7 sau đây được sử dụng bởi mô-đun chuyển đổi Node ? (Xem node_convert_node_convert()
trong 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()
chứa mã sau đây.
// &$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]);
}