Skip to content
Snippets Groups Projects
Commit b23a2bbe authored by Mingsong Hu's avatar Mingsong Hu
Browse files

Refactor the algorithm for updating hierarchy

parent 0ffe506d
No related branches found
Tags 3.0.3
No related merge requests found
......@@ -100,7 +100,7 @@
}
if (data.position < list.length - 1) {
after = list[data.position + 1];
after = list[data.position];
}
// Update the data on server side.
......@@ -109,6 +109,7 @@
target: data.position,
parent: parent,
old_parent: old_parent,
old_position: data.old_position,
after: after,
before: before
})
......
......@@ -170,6 +170,7 @@ class HmMenuController extends ControllerBase {
return new Response($this->t('Access denied!'));
}
$old_position = (int) $request->get('old_position');
$target_position = $request->get('target');
$parent = $request->get('parent');
$updated_links = $request->get('keys');
......@@ -220,7 +221,7 @@ class HmMenuController extends ControllerBase {
}
}
$new_hierarchy = $this->hmPluginTypeManager->updateHierarchy($target_position, $all_siblings, $updated_links);
$new_hierarchy = $this->hmPluginTypeManager->updateHierarchy($target_position, $all_siblings, $updated_links, $old_position);
foreach ($updated_links as $id) {
if (!isset($links_uuid[$id])) {
$entity = $this->entityTypeManager->getStorage('menu_link_content')->load($id);
......
......@@ -166,6 +166,7 @@ class HmTaxonomyController extends ControllerBase {
}
$target_position = $request->get('target');
$old_position = (int) $request->get('old_position');
$old_parent_id = $request->get('old_parent');
// Remove the parent index from the parent id.
$old_parent_id = explode('_', $old_parent_id)[0];
......@@ -199,7 +200,7 @@ class HmTaxonomyController extends ControllerBase {
}
}
$new_hierarchy = $this->hmPluginTypeManager->updateHierarchy($target_position, $all_siblings, $updated_terms);
$new_hierarchy = $this->hmPluginTypeManager->updateHierarchy($target_position, $all_siblings, $updated_terms, $old_position);
$tids = array_keys($new_hierarchy);
// Load all terms needed to update.
......
......@@ -111,78 +111,96 @@ class PluginTypeManager {
* All siblings of the new items in an array[$item_id => (int)$weight]
* @param array $updated_items
* IDs of new items inserted.
* @param int|bool $after
* Indicator if new items are inserted after target position.
* @param int $weight
* The initial weight.
* @param int $old_position
* The old position of moving items.
*
* @return array
* All siblings needed to move and their new weights.
*/
public function updateHierarchy(int $target_position, array $all_siblings, array $updated_items, $after = true, int $weight = 0) {
public function updateHierarchy(int $target_position, array $all_siblings, array $updated_items, int $old_position) {
$new_hierarchy = [];
if (!empty($all_siblings)) {
$total = count($all_siblings);
$num_new = count(array_diff($updated_items, array_keys($all_siblings)));
// If there is new child,
// the insert position should move backward.
$insert_position = $target_position - $num_new;
if ($target_position <= 0) {
// The insert postion is the first position.
// we don't need to move any siblings.
$weight = reset($all_siblings) - 1;
}
elseif ($insert_position >= $total - 1) {
elseif ($target_position >= $total - 1) {
// The insert postion is the end,
// we don't need to move any siblings.
$last_item= array_slice($all_siblings, -1, 1, TRUE);
$weight = reset($last_item) + 1;
}
else {
$target_item = array_slice($all_siblings, $insert_position, 2);
$pre_weight = $target_item[0];
$next_weight = $target_item[1];
$weight = $pre_weight + 1;
$target_item = array_slice($all_siblings, $target_position, 1);
$weight = $target_item[0];
$total_insert = count($updated_items);
// Figure out if the target element should move forward.
if ($num_new || ($old_position > $target_position)) {
$move_forward = true;
}
else {
$move_forward = false;
}
if ($next_weight - $pre_weight <= $total_insert) {
// The gap is not big enough.
// Need to make some room.
// If the target position is in the second half,
// we will move all siblings
// after the target position forward.
// Otherwise, we will move siblings
// before the target position backwards.
if ($insert_position >= $total / 2) {
$moving_siblings = array_slice($all_siblings, $insert_position + 1, NULL, TRUE);
$after = true;
$expected_weight = $next_weight + 1 + $total_insert;
// If the target position is in the second half,
// we will move all siblings
// after the target position forward.
// Otherwise, we will move siblings
// before the target position backwards.
if ($target_position - $num_new >= $total / 2) {
if ($move_forward) {
$moving_siblings = array_slice($all_siblings, $target_position, NULL, TRUE);
$weight = $target_item[0];
}
else {
$moving_siblings = array_slice($all_siblings, $target_position + 1, NULL, TRUE);
$weight = $target_item[0] + 1;
}
$after = true;
$expected_weight = $weight + $total_insert;
}
// Move the first bundle.
else {
if ($move_forward) {
$moving_siblings = array_slice($all_siblings, 0, $target_position, TRUE);
$weight = $target_item[0] - 1;
}
else {
$moving_siblings = array_slice($all_siblings, 0, $insert_position + 1, TRUE);
$after = false;
$weight = $next_weight - 1;
$expected_weight = $pre_weight - count($moving_siblings);
$moving_siblings = array_slice($all_siblings, 0, $target_position + 1, TRUE);
$weight = $target_item[0];
}
$after = false;
$expected_weight = $weight - count($moving_siblings) - $total_insert + 1;
}
// Move all siblings that need to move.
foreach($moving_siblings as $item_id => $item_weight) {
// Skip all links in the updated array. They will be moved later.
if (in_array($item_id, $updated_items)) {
continue;
}
if ($after) {
if ($item_weight < $expected_weight) {
$new_hierarchy[$item_id] = $expected_weight++;
}
// Move all siblings that need to move.
foreach($moving_siblings as $item_id => $item_weight) {
// Skip all items that are in the updated array.
// They will be moved later.
if (in_array($item_id, $updated_items)) {
continue;
}
if ($after) {
if ($item_weight < $expected_weight) {
$new_hierarchy[$item_id] = $expected_weight;
}
else {
if ($item_weight > $expected_weight) {
$new_hierarchy[$item_id] = $expected_weight++;
}
// The weight is bigger than expected.
// No need to move the rest of siblings.
break;
}
}
else {
if ($item_weight > $expected_weight) {
$new_hierarchy[$item_id] = $expected_weight;
}
}
// Move to next sibling.
$expected_weight++;
}
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment