我注意到没有从数据库中删除段落实体。它们更倾向于从父节点断开链接。
如果您创建一个视图,该视图列出段落并附加上下文过滤器,通过Parent ID进行筛选,则这一点非常明显。
现在,我已经找到了一个解决办法,可以创建一个列出内容的视图。将关系附加到某一段落。这样可以确保只显示链接的段落。
数据库中仍然存在数百个孤儿段落和字段数据的问题。有办法清洗它们吗?
编辑:这显然是一个主要的错误,可以在段落模块的问题跟踪器:删除的段落实体未从数据库中删除中找到
发布于 2018-04-25 12:12:16
现在我已经意识到这是一个bug,而且它还没有被修复,我的主要目标是只清理孤儿段落。
有人创建了这个模块:段落干净,但我不喜欢为此目的使用模块。
因此,下面我将发布我的第一次成功尝试来解决这个问题。我必须警告,这是不安全的,因为它删除了段落!
解决方案没有测试使用修订,内容翻译等。因此,这可能会毁了你的一天。备份您的站点。
使用Devel模块,转到Development > Execute PHP Code。粘贴并执行以下代码:
// get all paragraphs
$deleted = [];
$paragraph_ids = \Drupal::entityQuery('paragraph')->execute();
$paragraphs = \Drupal::entityTypeManager()->getStorage('paragraph')->loadMultiple($paragraph_ids);
foreach ($paragraphs as $target_id => $paragraph) {
// get parent entity (node, taxonomy, paragraph, etc.)
$parent = $paragraph->getParentEntity();
$field_name = $paragraph->parent_field_name->value;
// Check if current paragraph exists in parent entity field values
$exists = FALSE;
$values = is_null($parent) ? [] : $parent->get($field_name)->getValue();
foreach($values as $value) {
if ($value['target_id'] == $target_id) {
$exists = TRUE;
}
}
// Delete paragraphs that aren't linked to an entity they claim as a parent
if (!$exists) {
$paragraph->delete();
$deleted[] = $target_id;
}
}
print "Deleted paragraph IDs: " . implode(', ', $deleted);发布于 2019-09-24 15:17:10
我们创建了一个名为paragraphs_clean的模块,它实现了hook_entity_update() (注意:模块名必须等于entity_update()钩子函数的前缀),从这里获得灵感:https://www.drupal.org/project/paragraphs/issues/2741937#comment-13181377。
正如所述,即使有修订和翻译,它似乎运作良好。另外,当段落也有段落(即嵌套段落)时,我们必须修改原来的php代码以发挥作用。
这段代码比上面的代码更高效,因为它只会从上下文中加载实体的孤立段落。
以下是代码:
<?php
/**
* @file
* Paragraphs clean module.
*/
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\field\Entity\FieldConfig;
/**
* Implements hook_entity_update().
*
* When form updates, delete any paragraph entities that were removed.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
*/
function paragraphs_clean_entity_update(EntityInterface $entity) {
// Only act on content entities.
if (!($entity instanceof FieldableEntityInterface)) {
return;
}
$fieldManager = \Drupal::service('entity_field.manager');
$parentEntities = $fieldManager->getFieldMapByFieldType('entity_reference_revisions');
if (!array_key_exists($entity->getEntityTypeId(), $parentEntities)) {
return;
}
$paragraph_definitions = [];
// loop through all paragraph types
foreach ($parentEntities[$entity->getEntityTypeId()] as $field_id => $settings) {
if ($configField = FieldConfig::loadByName($entity->getEntityTypeId(), $entity->bundle(), $field_id)) {
$paragraph_definitions[] = $configField;
}
}
if (empty($paragraph_definitions)) {
return;
}
foreach ($paragraph_definitions as $paragraph_definition) {
//get entity type name to make it work with any kind of parent entity (node, paragraph, etc.)
$entityTypeName = $entity->getEntityTypeId();
// Remove orphaned paragraphs.
$query = \Drupal::database()->select('paragraphs_item_field_data', 'pfd')
->fields('pfd', ['id'])
->condition('pfd.parent_type', $entityTypeName)
->condition('pfd.parent_id', $entity->id())
->condition('pfd.parent_field_name', $paragraph_definition->getName());
$query->addJoin('left', $entityTypeName.'__'.$paragraph_definition->getName(),'nt','pfd.id=nt.'.$paragraph_definition->getName().'_target_id');
$query->isNull('nt.'.$paragraph_definition->getName().'_target_id');
$query->distinct();
$paragraph_ids = $query->execute()->fetchCol();
if ($paragraph_ids) {
$para_storage = \Drupal::entityTypeManager()->getStorage('paragraph');
foreach ($paragraph_ids as $paragraph_id) {
if ($para = $para_storage->load($paragraph_id)) {
$para->delete();
drupal_set_message(t('Paragraph of type "%type" has been deleted: %id', ['%id' => $paragraph_id, '%type' => $paragraph_definition->getName()]));
}
}
}
}
}https://stackoverflow.com/questions/50016160
复制相似问题