タイプ 計算フィールド のフィールドを既存のノードに追加しました。計算されたフィールド値を設定/更新するには、ノードを再保存する必要があります。変更したタイムスタンプを更新したくないので、ビューの一括更新を使用してコンテンツを再保存しないことにしました。最も簡単な方法はDrushスクリプトであり、必要なときにいつでもコンテンツを再保存できます。
私の最初の問題は、更新($ node-> save())で変更時刻を変更せずにおくことができなかったことです。しかし、2番目のノードの保存時に再設定できることがわかりました。
私の問題は、各ノードに新しいリビジョンが保存されることです。ノードタイプはリビジョン可能であり、コアモジュールの横でコンテンツ管理が有効になっています。リビジョンの作成を防ぐ方法について、何か助けていただければ幸いです。
これは、custom_helper.drush.incにある私の現在のDrushスクリプトです。
<?php
/**
* @file
* Provides drush command to update all articles.
*/
use Drupal\node\Entity\Node;
/**
* Implements hook_drush_command().
*/
function custom_helper_drush_command() {
$items = array();
$items['custom-resave-content'] = array(
'description' => dt('Resaves all article entities.'),
'options' => [
'types' => dt('Coma separated list of content type to be resaved.'),
'nids' => dt('Coma separated list if node ids.'),
'field' => dt('Machine name of computed field to be updated.')
],
'aliases' => array('custom-rc'),
);
return $items;
}
/**
* Moves paragraphs into one paragraph reference field.
*/
function drush_custom_helper_custom_resave_content() {
$nids = _convert_csv_to_array(drush_get_option('nids', []));
$types = _convert_csv_to_array(drush_get_option('types', []));
if (!$nids || $types) {
// Get an array of node IDs.
$query = \Drupal::entityQuery('node');
if ($types) {
$query->condition('type', $types, 'IN');
}
if ($nids) {
$query->condition('nid', $nids, 'IN');
}
$nids = $query->execute();
}
// Load all the nodes.
if ($nids) {
$field_name = drush_get_option('field', '');
$nodes = Node::loadMultiple($nids);
foreach ($nodes as $node) {
$entity_type = $node->getEntityType();
$original_changed = $node->getChangedTime();
if ($entity_type->isRevisionable()) {
$node->setNewRevision(FALSE);
}
// Force update of computed field.
if ($field_name) {
/** @var \Drupal\Core\Field\FieldItemListInterface $items */
$items = $node->get($field_name);
if (empty($items[0])) {
$items->appendItem();
}
$items->preSave();
}
// Save the updated computed field value.
$node->setChangedTime($original_changed);
if ($entity_type->isRevisionable()) {
$node->setNewRevision(FALSE);
}
$node->save();
// Reset changed time to original value.
$node->setChangedTime($original_changed);
if ($entity_type->isRevisionable()) {
$node->setNewRevision(FALSE);
}
$node->save();
$changed_after = $node->getChangedTime();
drush_print('node:' . $node->id() . ':' . $original_changed . ':' . $changed_after);
}
}
drush_log(dt('Resave finished.'), 'ok');
}
現在のところ、ノードエンティティタイプのモデレートハンドラーを置き換えるなどのバックフリップを行わずにコンテンツモデレーションをインストールした場合、これは不可能です。
ただし、これは作業中です!発生している問題に関連するいくつかの問題を次に示します。
提案は本質的に2つの方向に分かれています:
SynchronizableInterface::setSyncing()
の呼び出し元に適切に説明します。問題から自分自身を引用:
IMO、コンテンツエンティティの現在の「同期中」ステータスは、通常のユーザーが開始したコンテンツ更新の範囲外の状況で保存が行われていること、およびその保存による副作用が可能な限り多いことを示すフラグに形作られています限られた。例は次のとおりです。
- ワークスペースを展開する。
- 古いリビジョンのバッチ更新。
- 移行からの更新の実行。
これらのシナリオのいくつかを定義した後、議論されたいくつかの副作用(CMリビジョン処理+変更されたタイムスタンプ)の排除を合理化することがより簡単になります。
あなたのケースでは、既存のエンティティ/リビジョンを一括更新することでモデルの整合性を解決しようとしています。これは標準の編集ベースのコンテンツ変更の範囲外であるため、私の意見では、コンテンツエンティティとこれに提案されているセマンティクスに非常に明確に適合しています。インターフェース。したがって、これらのパッチのいくつかを適用すると、コードサンプルは次のようになります。
$entity->setSyncing(TRUE);
$node->save();
そして、変更されたタイムスタンプは更新されず、コンテンツの管理は新しいリビジョンの作成を強制しません。