Skip to content
Snippets Groups Projects
Commit 21f09598 authored by Lee Rowlands's avatar Lee Rowlands
Browse files

Issue #2858617 by larowlan: Add the ability to rebuild a nested set...

Issue #2858617 by larowlan: Add the ability to rebuild a nested set representation of the hierarchy: test
parent ec37f882
No related branches found
No related tags found
No related merge requests found
<?php
/**
* @file
* Contains drush commands for the module.
*/
/**
* Implements hook_drush_command().
*/
function entity_hierarchy_drush_command() {
$items = array();
$items['entity-hierarchy-rebuild-tree'] = array(
'description' => 'Rebuild tree.',
'arguments' => array(
'field_name' => dt('Field machine name'),
'entity_type_id' => dt('Entity type id'),
),
'options' => array(),
'examples' => array(
'drush entity-hierarchy-rebuild-tree field_parents node' => 'Rebuild tree for node field named field_parents.',
),
);
return $items;
}
/**
* Rebuild the tree.
*/
function drush_entity_hierarchy_rebuild_tree($field_name, $entity_type_id) {
$tasks = \Drupal::service('entity_hierarchy.tree_rebuilder')->getRebuildTasks($field_name, $entity_type_id);
batch_set($tasks);
$batch =& batch_get();
$batch['progressive'] = FALSE;
drush_backend_batch_process();
}
......@@ -15,3 +15,6 @@ services:
entity_hierarchy.entity_tree_node_mapper:
class: Drupal\entity_hierarchy\Storage\EntityTreeNodeMapper
arguments: ['@entity_type.manager']
entity_hierarchy.tree_rebuilder:
class: Drupal\entity_hierarchy\Storage\TreeRebuilder
arguments: ['@entity_type.manager']
<?php
namespace Drupal\entity_hierarchy\Storage;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
/**
* Defines a class for rebuilding the tree.
*/
class TreeRebuilder {
/**
* Entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* Constructs a new TreeRebuilder object.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
* Entity type manager.
*/
public function __construct(EntityTypeManagerInterface $entityTypeManager) {
$this->entityTypeManager = $entityTypeManager;
}
/**
* Gets rebuild tasks suitable for usage with batch_set().
*
* @param string $field_name
* Field name to rebuild.
* @param string $entity_type_id
* Entity Type to rebuild.
*
* @return array
* Batch definition.
*/
public function getRebuildTasks($field_name, $entity_type_id) {
$batch = [
'title' => new TranslatableMarkup('Rebuilding tree for field @field, @entity_type_id ...', [
'@field' => $field_name,
'@entity_type_id' => $entity_type_id,
]),
'operations' => [
[[static::class, 'removeTable'], [$field_name, $entity_type_id]],
],
'finished' => [static::class, 'batchFinished'],
];
foreach ($this->entityTypeManager->getStorage($entity_type_id)->getQuery()->exists($field_name)->execute() as $entity_id) {
$batch['operations'][] = [
[static::class, 'rebuildTree'],
[$field_name, $entity_type_id, $entity_id],
];
}
return $batch;
}
/**
* Batch callback to remove table.
*
* @param string $field_name
* Field name.
* @param string $entity_type_id
* Entity Type ID.
*/
public static function removeTable($field_name, $entity_type_id) {
\Drupal::database()->schema()->dropTable(\Drupal::service('entity_hierarchy.nested_set_storage_factory')->getTableName($field_name, $entity_type_id, FALSE));
}
/**
* Batch callback to rebuild the tree.
*
* @param string $field_name
* Field name.
* @param string $entity_type_id
* Entity type ID.
* @param mixed $entity_id
* Entity ID.
* @param array $context
* Batch context.
*/
//@codingStandardsIgnoreStart
public static function rebuildTree($field_name, $entity_type_id, $entity_id, &$context) {
//@codingStandardsIgnoreEnd
$entity = \Drupal::entityTypeManager()->getStorage($entity_type_id)->load($entity_id);
$entity->get($field_name)->postSave(TRUE);
$context['results'][] = $entity_id;
}
/**
* Finished callback.
*
* @param bool $success
* TRUE if succeeded.
* @param int $results
* Results.
* @param array $operations
* Operations.
*/
//@codingStandardsIgnoreStart
public static function batchFinished($success, $results, $operations) {
//@codingStandardsIgnoreEnd
if ($success) {
// Here we do something meaningful with the results.
$message = new TranslatableMarkup('Finished rebuilding tree, @count items were processed.', [
'@count' => count($results),
]);
drupal_set_message($message);
}
else {
// An error occurred.
// $operations contains the operations that remained unprocessed.
$error_operation = reset($operations);
$message = new TranslatableMarkup('An error occurred while processing %error_operation with arguments: @arguments', [
'%error_operation' => implode('::', $error_operation[0]),
'@arguments' => print_r($error_operation[1], TRUE),
]);
drupal_set_message($message, 'error');
}
}
}
<?php
namespace Drupal\Tests\entity_hierarchy\Kernel;
use PNX\NestedSet\Node;
use PNX\NestedSet\NodeKey;
......@@ -11,8 +12,11 @@ use PNX\NestedSet\NodeKey;
*/
class RebuildTest extends EntityHierarchyKernelTestBase {
/**
* Tests rebuilding.
*/
public function testRebuild() {
$entities = $this->createChildEntities($this->parent->id());
$this->createChildEntities($this->parent->id());
$expected = [
new Node(new NodeKey('1', '1'), '1', '12', '0'),
new Node(new NodeKey('6', '6'), '2', '3', '1'),
......@@ -26,14 +30,17 @@ class RebuildTest extends EntityHierarchyKernelTestBase {
$this->container->get('database')->update('nested_set_parents_entity_test')
->fields([
'left_pos' => 4,
'right_pos' => 5
'right_pos' => 5,
])
->condition('id', 2)
->execute();
$this->assertNotEquals($expected, $this->treeStorage->getTree());
$rebuild_tasks = $this->container->get('entity_hierarchy.tree_rebuilder')->getRebuildTasks();
batch_set($rebuild_tasks + ['progressive' => FALSE]);
$rebuild_tasks = $this->container->get('entity_hierarchy.tree_rebuilder')->getRebuildTasks(self::FIELD_NAME, self::ENTITY_TYPE);
batch_set($rebuild_tasks);
$batch =& batch_get();
$batch['progressive'] = FALSE;
batch_process();
$this->assertEquals($expected, $this->treeStorage->getTree());
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment