Skip to content
Snippets Groups Projects

Improvements to allow clone book entities.

1 unresolved thread
2 files
+ 118
3
Compare changes
  • Side-by-side
  • Inline
Files
2
@@ -13,6 +13,7 @@ use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Entity\TranslatableInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Field\FieldConfigInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Session\AccountProxyInterface;
@@ -60,6 +61,13 @@ class ContentEntityCloneBase implements EntityHandlerInterface, EntityCloneInter
*/
protected $currentUser;
/**
* The module handler service.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected $moduleHandler;
/**
* Constructs a new ContentEntityCloneBase.
*
@@ -73,13 +81,16 @@ class ContentEntityCloneBase implements EntityHandlerInterface, EntityCloneInter
* The current user.
* @param \Drupal\entity_clone\EntityCloneClonableFieldInterface $entity_clone_clonable_field
* The entity clone clonable field service.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler service.
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager, string $entity_type_id, TimeInterface $time_service, AccountProxyInterface $current_user, EntityCloneClonableFieldInterface $entity_clone_clonable_field) {
public function __construct(EntityTypeManagerInterface $entity_type_manager, string $entity_type_id, TimeInterface $time_service, AccountProxyInterface $current_user, EntityCloneClonableFieldInterface $entity_clone_clonable_field, ModuleHandlerInterface $module_handler) {
$this->entityTypeManager = $entity_type_manager;
$this->entityTypeId = $entity_type_id;
$this->timeService = $time_service;
$this->currentUser = $current_user;
$this->entityCloneClonableField = $entity_clone_clonable_field;
$this->moduleHandler = $module_handler;
}
/**
@@ -91,7 +102,8 @@ class ContentEntityCloneBase implements EntityHandlerInterface, EntityCloneInter
$entity_type->id(),
$container->get('datetime.time'),
$container->get('current_user'),
$container->get('entity_clone.clonable_field')
$container->get('entity_clone.clonable_field'),
$container->get('module_handler')
);
}
@@ -99,6 +111,25 @@ class ContentEntityCloneBase implements EntityHandlerInterface, EntityCloneInter
* {@inheritdoc}
*/
public function cloneEntity(EntityInterface $entity, EntityInterface $cloned_entity, array $properties = [], array &$already_cloned = []) {
// Clone books entities.
$bid = isset($entity->book) && empty($entity->book['bid']) ? 0 : $entity->book['bid'];
if (!empty($properties['clone_book']) && !empty($bid) && $entity->book['bid'] == $entity->id()) {
// This is the parent book.
$link = [
'nid' => $cloned_entity->id(),
'bid' => 'new',
'pid' => 0,
'has_children' => $entity->book['has_children'],
'weight' => 0,
'depth' => 1,
];
$cloned_entity->book = $link;
$cloned_entity->save();
// Clone book children.
$this->cloneBookPages($entity, $cloned_entity, $properties);
}
    • Comment on lines +114 to +132

      can we add condition:

      Suggested change
      114 // Clone books entities.
      115 $bid = isset($entity->book) && empty($entity->book['bid']) ? 0 : $entity->book['bid'];
      116 if (!empty($properties['clone_book']) && !empty($bid) && $entity->book['bid'] == $entity->id()) {
      117 // This is the parent book.
      118 $link = [
      119 'nid' => $cloned_entity->id(),
      120 'bid' => 'new',
      121 'pid' => 0,
      122 'has_children' => $entity->book['has_children'],
      123 'weight' => 0,
      124 'depth' => 1,
      125 ];
      126 $cloned_entity->book = $link;
      127 $cloned_entity->save();
      128
      129 // Clone book children.
      130 $this->cloneBookPages($entity, $cloned_entity, $properties);
      131 }
      132
      114 // Clone books entities.
      115 if ($this->moduleHandler->moduleExist('book')) {
      116 $bid = isset($entity->book) && empty($entity->book['bid']) ? 0 : $entity->book['bid'];
      117 if (!empty($properties['clone_book']) && !empty($bid) && $entity->book['bid'] == $entity->id()) {
      118 // This is the parent book.
      119 $link = [
      120 'nid' => $cloned_entity->id(),
      121 'bid' => 'new',
      122 'pid' => 0,
      123 'has_children' => $entity->book['has_children'],
      124 'weight' => 0,
      125 'depth' => 1,
      126 ];
      127 $cloned_entity->book = $link;
      128 $cloned_entity->save();
      129
      130 // Clone book children.
      131 $this->cloneBookPages($entity, $cloned_entity, $properties);
      132 }
      133 }
Please register or sign in to reply
// Clone referenced entities.
$already_cloned[$entity->getEntityTypeId()][$entity->id()] = $cloned_entity;
if ($cloned_entity instanceof FieldableEntityInterface && $entity instanceof FieldableEntityInterface) {
@@ -122,7 +153,10 @@ class ContentEntityCloneBase implements EntityHandlerInterface, EntityCloneInter
}
}
$this->setClonedEntityLabel($entity, $cloned_entity, $properties);
// Only change the label on single nodes, fixing the title on entire books is too cumbersome.
if (empty($properties['clone_book'])) {
$this->setClonedEntityLabel($entity, $cloned_entity, $properties);
}
$this->setCreatedAndChangedDates($cloned_entity);
if ($this->hasTranslatableModerationState($cloned_entity)) {
@@ -365,4 +399,66 @@ class ContentEntityCloneBase implements EntityHandlerInterface, EntityCloneInter
}
}
/**
* Clone the book pages within a book.
*
* @param \Drupal\Core\Entity\EntityInterface $original_entity
* The original entity.
* @param \Drupal\Core\Entity\EntityInterface $cloned_entity
* The entity cloned from the original.
* @param array $properties
* The properties argument containing the bid and nid map.
*/
protected function cloneBookPages(EntityInterface $original_entity, EntityInterface $cloned_entity, array $properties) {
$bid = $cloned_entity->id();
$map = [
$original_entity->id() => $cloned_entity->id(),
];
$children = \Drupal::service('book.outline_storage')->loadBookChildren($original_entity->id());
$this->cloneBookChildren($children, $properties, $bid, $map);
}
/**
* Recursive method to walk the children and clone.
*
* @param array $children
* The current pages children.
* @param array $properties
* The properties argument containing the bid and nid map.
* @param int $bid
* The book id.
* @param array $map
* The map argument containing the old nid to new map to set the new parent properly.
*/
protected function cloneBookChildren(array $children, array $properties, int $bid, array &$map) {
foreach ($children as $nid => $child) {
$entity = $this->entityTypeManager->getStorage('node')->load($nid);
$duplicate = $entity->createDuplicate();
$cloned_entity = $this->cloneEntity($entity, $duplicate, $properties);
// Set the moderation state in children books according to user's choice.
if ($this->moduleHandler->moduleExists('content_moderation') && isset($properties['moderation_state']) && $duplicate->hasField('moderation_state')) {
$duplicate->set('moderation_state', $properties['moderation_state']);
}
$link = [
'nid' => $cloned_entity->id(),
'bid' => $bid,
'pid' => !empty($map[$entity->book['pid']]) ? $map[$entity->book['pid']] : $bid,
'weight' => $entity->book['weight'],
'depth' => $entity->book['depth'],
];
$cloned_entity->book = $link;
$cloned_entity->save();
$map[$entity->id()] = $cloned_entity->id();
if ($child['has_children'] == 1) {
$next_level = \Drupal::service('book.outline_storage')->loadBookChildren($nid);
$this->cloneBookChildren($next_level, $properties, $bid, $map);
}
}
}
}
Loading