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

Improve hierarchy update algorithm

parent d2c9e782
No related branches found
No related tags found
No related merge requests found
...@@ -168,6 +168,8 @@ class HmMenuController extends ControllerBase { ...@@ -168,6 +168,8 @@ class HmMenuController extends ControllerBase {
$updated_links = $request->get('keys'); $updated_links = $request->get('keys');
//$after = $request->get('after'); //$after = $request->get('after');
$before = $request->get('before'); $before = $request->get('before');
$all_siblings = [];
$insert_after = TRUE;
if (is_array($updated_links) && !empty($updated_links)) { if (is_array($updated_links) && !empty($updated_links)) {
if (empty($parent)) { if (empty($parent)) {
...@@ -186,48 +188,39 @@ class HmMenuController extends ControllerBase { ...@@ -186,48 +188,39 @@ class HmMenuController extends ControllerBase {
// The parent menu doesn't exist. // The parent menu doesn't exist.
return new JsonResponse(['result' => 'fail']); return new JsonResponse(['result' => 'fail']);
} }
else {
if (empty($children)) {
$parent_link = reset($parent_links);
$children = $parent_link->subtree;
}
if ($children) { if (empty($children)) {
// The parent menu has children. $parent_link = reset($parent_links);
$target_position = intval($target_position); $children = $parent_link->subtree;
$all_siblings = []; }
$insert_after = TRUE;
$position = 0; if ($children) {
foreach ($children as $child) { // The parent menu has children.
$link = $child->link; $target_position = intval($target_position);
$link_id = $link->getPLuginId();
// Figure out if the new links are inserted $position = 0;
// after the target position. foreach ($children as $child) {
if ($position++ == $target_position && $link_id !== $before) { $link = $child->link;
$insert_after = FALSE; $link_id = $link->getPLuginId();
} // Figure out if the new links are inserted
// after the target position.
$all_siblings[$link_id] = (int) $link->getWeight(); if ($position++ == $target_position && $link_id !== $before) {
$insert_after = FALSE;
} }
$new_hierarchy = $this->hmPluginTypeManager->updateHierarchy($target_position, $all_siblings, $updated_links, $insert_after); $all_siblings[$link_id] = (int) $link->getWeight();
$weight = $new_hierarchy['start_weight'];
$moving_siblings = $new_hierarchy['moving_siblings'];
// Update all sibling links needed to update.
foreach ($moving_siblings as $link_id => $link_weight) {
$this->menuLinkManager->updateDefinition($link_id, ['weight' => $link_weight]);
}
}
else {
// The parent link doesn't have children.
$weight = 0;
}
// Move all links updated.
foreach ($updated_links as $link_id) {
$this->menuLinkManager->updateDefinition($link_id, ['weight' => $weight++, 'parent' => $parent]);
} }
} }
else {
// The parent link doesn't have children.
}
$new_hierarchy = $this->hmPluginTypeManager->updateHierarchy($target_position, $all_siblings, $updated_links, $insert_after);
// Update all links need to update.
foreach ($new_hierarchy as $link_id => $link_weight) {
$this->menuLinkManager->updateDefinition($link_id, ['weight' => $link_weight, 'parent' => $parent]);
}
return new JsonResponse(['result' => 'success']); return new JsonResponse(['result' => 'success']);
} }
......
...@@ -146,6 +146,8 @@ class HmTaxonomyController extends ControllerBase { ...@@ -146,6 +146,8 @@ class HmTaxonomyController extends ControllerBase {
//$after = $request->get('after'); //$after = $request->get('after');
$before = $request->get('before'); $before = $request->get('before');
$success = FALSE; $success = FALSE;
$insert_after = TRUE;
$all_siblings = [];
if (is_array($updated_terms) && !empty($updated_terms)) { if (is_array($updated_terms) && !empty($updated_terms)) {
// Taxonomy access control. // Taxonomy access control.
...@@ -156,7 +158,6 @@ class HmTaxonomyController extends ControllerBase { ...@@ -156,7 +158,6 @@ class HmTaxonomyController extends ControllerBase {
if (empty($children)) { if (empty($children)) {
if (Term::load($parent_id)) { if (Term::load($parent_id)) {
// The parent term hasn't had any children. // The parent term hasn't had any children.
$weight = 0;
} }
else { else {
// The parent term doesn't exist. // The parent term doesn't exist.
...@@ -166,8 +167,6 @@ class HmTaxonomyController extends ControllerBase { ...@@ -166,8 +167,6 @@ class HmTaxonomyController extends ControllerBase {
else { else {
// The parent term has children. // The parent term has children.
$target_position = intval($target_position); $target_position = intval($target_position);
$all_siblings = [];
$insert_after = TRUE;
$position = 0; $position = 0;
foreach ($children as $child) { foreach ($children as $child) {
...@@ -179,30 +178,18 @@ class HmTaxonomyController extends ControllerBase { ...@@ -179,30 +178,18 @@ class HmTaxonomyController extends ControllerBase {
$all_siblings[$child->tid] = (int) $child->weight; $all_siblings[$child->tid] = (int) $child->weight;
} }
$new_hierarchy = $this->hmPluginTypeManager->updateHierarchy($target_position, $all_siblings, $updated_terms, $insert_after);
$weight = $new_hierarchy['start_weight'];
$moving_siblings = $new_hierarchy['moving_siblings'];
$tids = array_keys($moving_siblings);
if (!empty($tids)) {
// Update siblings.
$term_siblings = Term::loadMultiple($tids);
foreach ($term_siblings as $term) {
$term->setWeight($moving_siblings[$term->id()]);
$success = $term->save();
}
}
} }
$new_hierarchy = $this->hmPluginTypeManager->updateHierarchy($target_position, $all_siblings, $updated_terms, $insert_after);
$tids = array_keys($new_hierarchy);
// Load all terms needed to update. // Load all terms needed to update.
$terms = Term::loadMultiple($updated_terms); $terms = Term::loadMultiple($tids);
// Update all terms, the weight will be increased by 1, // Update all terms.
// after inserting.
foreach ($terms as $term) { foreach ($terms as $term) {
if ($access_control_handler->access($term, 'update')) { if ($access_control_handler->access($term, 'update')) {
$term->set('parent', ['target_id' => $parent_id]); $term->set('parent', ['target_id' => $parent_id]);
$term->setWeight($weight++); $term->setWeight($new_hierarchy[$term->id()]);
$success = $term->save(); $success = $term->save();
} }
} }
......
...@@ -97,107 +97,115 @@ class PluginTypeManager { ...@@ -97,107 +97,115 @@ class PluginTypeManager {
* IDs of new items inserted. * IDs of new items inserted.
* @param int|bool $after * @param int|bool $after
* Indicator if new items are inserted after target position. * Indicator if new items are inserted after target position.
* @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) { public function updateHierarchy(int $target_position, array $all_siblings, array $updated_items, $after, int $weight = 0) {
$filtered_moving_siblings = []; $new_hierarchy = [];
$first_half = TRUE; $first_half = TRUE;
$total = count($all_siblings); if (!empty($all_siblings)) {
if ($target_position === 0) { $total = count($all_siblings);
// The insert postion is the first position. if ($target_position === 0) {
// we don't need to move any siblings. // The insert postion is the first position.
$weight = (int) reset($all_siblings) - 1; // we don't need to move any siblings.
} $weight = (int) reset($all_siblings) - 1;
elseif ($target_position >= $total - 1) { }
// The insert postion is the end, elseif ($target_position >= $total - 1) {
// we don't need to move any siblings. // The insert postion is the end,
$last_item= array_slice($all_siblings, -1, 1, TRUE); // we don't need to move any siblings.
$weight = (int) reset($last_item) + 1; $last_item= array_slice($all_siblings, -1, 1, TRUE);
} $weight = (int) reset($last_item) + 1;
else {
$target_item = array_slice($all_siblings, $target_position, 1, TRUE);
$weight = (int) reset($target_item);
// 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 >= $total / 2) {
$first_half = FALSE;
if ($after) {
// Insert after the target position.
// The target stay where it is.
$weight += 1;
$moving_siblings = array_slice($all_siblings, $target_position + 1, NULL, TRUE);
}
else {
// Insert before the target position.
// The target need to move forwards.
$moving_siblings = array_slice($all_siblings, $target_position, NULL, TRUE);
}
$step = $weight + count($updated_items);
} }
else { else {
if ($after) { $target_item = array_slice($all_siblings, $target_position, 1, TRUE);
// Insert after the target position. $weight = (int) reset($target_item);
// The target need to move backwards. // If the target position is in the second half,
$moving_siblings = array_slice($all_siblings, 0, $target_position + 1, TRUE); // we will move all siblings
// after the target position forward.
// Otherwise, we will move siblings
// before the target position backwards.
if ($target_position >= $total / 2) {
$first_half = FALSE;
if ($after) {
// Insert after the target position.
// The target stay where it is.
$weight += 1;
$moving_siblings = array_slice($all_siblings, $target_position + 1, NULL, TRUE);
}
else {
// Insert before the target position.
// The target need to move forwards.
$moving_siblings = array_slice($all_siblings, $target_position, NULL, TRUE);
}
$step = $weight + count($updated_items);
} }
else { else {
// Insert before the target position. if ($after) {
// The target stay where it is. // Insert after the target position.
$weight -= 1; // The target need to move backwards.
$moving_siblings = array_slice($all_siblings, 0, $target_position, TRUE); $moving_siblings = array_slice($all_siblings, 0, $target_position + 1, TRUE);
}
$weight = $step = $weight - count($updated_items);
// Reverse the siblings_moved array
// as we will decrease the weight
// starting from the first element
// and the new weight should be in
// an opposite order.
$moving_siblings = array_reverse($moving_siblings, TRUE);
}
// 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 ($first_half) {
// While moving the first half of the siblings,
// all moving siblings' weight are decreased,
// if they are greater than the step.
if ((int)$item_weight < --$step) {
// There is planty room, no need to move anymore.
break;
} }
else { else {
// Update the weight. // Insert before the target position.
$filtered_moving_siblings[$item_id] = $step; // The target stay where it is.
$weight -= 1;
$moving_siblings = array_slice($all_siblings, 0, $target_position, TRUE);
} }
$weight = $step = $weight - count($updated_items);
// Reverse the siblings_moved array
// as we will decrease the weight
// starting from the first element
// and the new weight should be in
// an opposite order.
$moving_siblings = array_reverse($moving_siblings, TRUE);
} }
else {
// While moving the second half of the siblings, // Move all siblings that need to move.
// all moving siblings' weight are increased, foreach($moving_siblings as $item_id => $item_weight) {
// if they are less than the step. // Skip all links in the updated array. They will be moved later.
if ((int)$item_weight < ++$step) { if (in_array($item_id, $updated_items)) {
// Update the weight. continue;
$filtered_moving_siblings[$item_id] = $step; }
if ($first_half) {
// While moving the first half of the siblings,
// all moving siblings' weight are decreased,
// if they are greater than the step.
if ((int)$item_weight < --$step) {
// There is planty room, no need to move anymore.
break;
}
else {
// Update the weight.
$new_hierarchy[$item_id] = $step;
}
} }
else { else {
// There is planty room, no need to move anymore. // While moving the second half of the siblings,
break; // all moving siblings' weight are increased,
// if they are less than the step.
if ((int)$item_weight < ++$step) {
// Update the weight.
$new_hierarchy[$item_id] = $step;
}
else {
// There is planty room, no need to move anymore.
break;
}
} }
} }
} }
} }
return ['start_weight' => $weight, 'moving_siblings' => $filtered_moving_siblings]; foreach ($updated_items as $item) {
$new_hierarchy[$item] = $weight++;
}
return $new_hierarchy;
} }
} }
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