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