From a3197a02011107d90b2f3a58d5d49011dc95c5c1 Mon Sep 17 00:00:00 2001 From: Michael Bauer Date: Wed, 5 Jan 2022 10:56:29 +0100 Subject: [PATCH] fill optional by-ref param for changed nodes --- src/GenericSortableTreeNode.php | 11 ++-- src/GenericTypedPayloadSortableTreeNode.php | 16 +++-- src/canProcessTreeNodeSortRequests.php | 67 +++++++++++---------- 3 files changed, 52 insertions(+), 42 deletions(-) diff --git a/src/GenericSortableTreeNode.php b/src/GenericSortableTreeNode.php index 13ab7bd..8ef69e7 100644 --- a/src/GenericSortableTreeNode.php +++ b/src/GenericSortableTreeNode.php @@ -18,14 +18,15 @@ class GenericSortableTreeNode extends GenericTreeNode implements SortableTreeNod public function addChildWithSorting(SortableTreeNode $child, ?int $sorting = null): void { if ($sorting !== null && !array_key_exists($sorting, $this->childrenWithSorting)) { - $this->childrenWithSorting[$sorting] = $child; + $newSorting = $sorting; + $this->childrenWithSorting[$newSorting] = $child; } else { $currentHighestSorting = 0; if ($this->getNoOfChildrenWithSorting() > 0) { $currentHighestSorting = max(array_keys($this->childrenWithSorting)); } - - $this->childrenWithSorting[($currentHighestSorting + 1)] = $child; + $newSorting = $currentHighestSorting + 1; + $this->childrenWithSorting[$newSorting] = $child; } parent::addChild($child); } @@ -33,8 +34,9 @@ public function addChildWithSorting(SortableTreeNode $child, ?int $sorting = nul /** * @param SortableTreeNode $childToRemove */ - public function removeChildWithSorting(SortableTreeNode $childToRemove): void + public function removeChildWithSorting(SortableTreeNode $childToRemove, ?array &$changedNodes = null): void { + $changedNodes = null === $changedNodes ? [] : $changedNodes; $sortingChildToRemove = $childToRemove->getPerLevelSorting(); ksort($this->childrenWithSorting); @@ -47,6 +49,7 @@ public function removeChildWithSorting(SortableTreeNode $childToRemove): void } elseif ($currentSorting > $sortingChildToRemove) { unset($this->childrenWithSorting[$currentSorting]); $this->childrenWithSorting[($currentSorting - 1)] = $childWithSorting; + $changedNodes[] = $childWithSorting; } } diff --git a/src/GenericTypedPayloadSortableTreeNode.php b/src/GenericTypedPayloadSortableTreeNode.php index a90a781..8f0743f 100644 --- a/src/GenericTypedPayloadSortableTreeNode.php +++ b/src/GenericTypedPayloadSortableTreeNode.php @@ -20,14 +20,15 @@ class GenericTypedPayloadSortableTreeNode extends GenericTypedPayloadTreeNode im public function addChildWithSorting(SortableTreeNode $child, ?int $sorting = null): void { if ($sorting !== null && !array_key_exists($sorting, $this->childrenWithSorting)) { - $this->childrenWithSorting[$sorting] = $child; + $newSorting = $sorting; + $this->childrenWithSorting[$newSorting] = $child; } else { $currentHighestSorting = 0; if ($this->getNoOfChildrenWithSorting() > 0) { $currentHighestSorting = max(array_keys($this->childrenWithSorting)); } - - $this->childrenWithSorting[($currentHighestSorting + 1)] = $child; + $newSorting = $currentHighestSorting + 1; + $this->childrenWithSorting[$newSorting] = $child; } parent::addChild($child); } @@ -35,8 +36,9 @@ public function addChildWithSorting(SortableTreeNode $child, ?int $sorting = nul /** * @param SortableTreeNode $childToRemove */ - public function removeChildWithSorting(SortableTreeNode $childToRemove): void + public function removeChildWithSorting(SortableTreeNode $childToRemove, ?array &$changedNodes = null): void { + $changedNodes = null === $changedNodes ? [] : $changedNodes; $sortingChildToRemove = $childToRemove->getPerLevelSorting(); ksort($this->childrenWithSorting); @@ -49,6 +51,7 @@ public function removeChildWithSorting(SortableTreeNode $childToRemove): void } elseif ($currentSorting > $sortingChildToRemove) { unset($this->childrenWithSorting[$currentSorting]); $this->childrenWithSorting[($currentSorting - 1)] = $childWithSorting; + $changedNodes[] = $childWithSorting; } } @@ -63,10 +66,13 @@ public function removeChildWithSorting(SortableTreeNode $childToRemove): void */ public function addChildWithTypedPayloadAndWithSorting(TypedPayloadSortableTreeNode $child, ?int $sorting = null): void { + $childPayload = $child->getPayload(); + $childPayloadPHPType = \gettype($childPayload); + $childPayloadPHPFQDN = \is_object($childPayload) ? $childPayload::class : null; if (parent::isTypedPayloadValid($child->getPayload(), $this->getPayloadType(), $this->getPayloadObjectFQDN())) { $this->addChildWithSorting($child, $sorting); } else { - throw new InvalidArgumentException("Could not add child with typed payload, type has to be [{$this->getPayloadType()}]"); + throw new InvalidArgumentException("Could not add child with typed payload, type has to be [{$this->getPayloadType()}] - actual type [$childPayloadPHPType] with fqdn [$childPayloadPHPFQDN]."); } } } diff --git a/src/canProcessTreeNodeSortRequests.php b/src/canProcessTreeNodeSortRequests.php index 484fc90..75e389a 100644 --- a/src/canProcessTreeNodeSortRequests.php +++ b/src/canProcessTreeNodeSortRequests.php @@ -10,48 +10,47 @@ trait canProcessTreeNodeSortRequests * @param SortableTreeNode $treeNodeToSort * @param int $newSorting */ - public static function processNewSortingRequest(SortableTreeNode $treeNodeToSort, int $newSorting): void + public static function processNewSortingRequest(SortableTreeNode $treeNodeToSort, int $newSorting, ?array &$changedNodes = null): void { + $changedNodes = null === $changedNodes ? [] : $changedNodes; $parentTreeNode = $treeNodeToSort->getParent(); if ($parentTreeNode instanceof SortableTreeNode && $parentTreeNode->getNoOfChildrenWithSorting() > 0) { - $childrenWithSorting = &$parentTreeNode->getChildrenWithSorting(); - $treeNodeToSortPerLevelSorting = $treeNodeToSort->getPerLevelSorting(); - $moveUpAction = $treeNodeToSortPerLevelSorting < $newSorting; - $moveDownAction = $treeNodeToSortPerLevelSorting > $newSorting; - if ($moveUpAction) { - ksort($childrenWithSorting); - } elseif ($moveDownAction) { - krsort($childrenWithSorting); + $currSorting = $treeNodeToSort->getPerLevelSorting(); + + if ($currSorting === $newSorting) { + return; } + $changedNodes[] = $treeNodeToSort; + $minAffectedSorting = min($currSorting, $newSorting); + $maxAffectedSorting = max($currSorting, $newSorting); + $targetMovesUp = $newSorting > $currSorting; - unset($childrenWithSorting[$treeNodeToSortPerLevelSorting]); + $childrenWithSortingRef = &$parentTreeNode->getChildrenWithSorting(); + ksort($childrenWithSortingRef); + $newChildArray = []; - /** @var SortableTreeNode $childWithSorting */ - foreach ($childrenWithSorting as $sorting => $childWithSorting) { - if ( - ($moveDownAction && - ($sorting < $newSorting || - $sorting > $treeNodeToSortPerLevelSorting)) || - ($moveUpAction && - ($sorting > $newSorting || - $sorting < $treeNodeToSortPerLevelSorting)) - ) { + /** @var SortableTreeNode $currNode */ + foreach ($childrenWithSortingRef as $sorting => $currNode) { + if ($sorting < $minAffectedSorting || $sorting > $maxAffectedSorting) { + $newChildArray[$sorting] = $currNode; + continue; + } + if ($sorting === $currSorting) { continue; } + $changedNodes[] = $currNode; - if ($moveDownAction) { - unset($childrenWithSorting[$sorting]); - $childrenWithSorting[($sorting + 1)] = $childWithSorting; - } elseif ($moveUpAction) { - unset($childrenWithSorting[$sorting]); - $childrenWithSorting[($sorting - 1)] = $childWithSorting; + if ($targetMovesUp) { + $newChildArray[($sorting - 1)] = $currNode; + } else { + $newChildArray[($sorting + 1)] = $currNode; } } - - $childrenWithSorting[$newSorting] = $treeNodeToSort; - ksort($childrenWithSorting); + $newChildArray[$newSorting] = $treeNodeToSort; + ksort($newChildArray); + $childrenWithSortingRef = $newChildArray; } } @@ -62,12 +61,14 @@ public static function processNewSortingRequest(SortableTreeNode $treeNodeToSort * @param integer $newSorting * @return void */ - public static function processMoveRequest(SortableTreeNode $nodeToMove, SortableTreeNode $newParentNode, int $newSorting): void + public static function processMoveRequest(SortableTreeNode $nodeToMove, SortableTreeNode $newParentNode, int $newSorting, ?array &$changedNodes = null): void { /** @var SortableTreeNode $nodeToMoveParent */ $nodeToMoveParent = $nodeToMove->getParent(); - $nodeToMoveParent->removeChildWithSorting($nodeToMove); - $newParentNode->addChildWithSorting($nodeToMove); - GenericSortableTreeNode::processNewSortingRequest($nodeToMove, $newSorting); + if ($nodeToMoveParent !== $newParentNode) { + $nodeToMoveParent->removeChildWithSorting($nodeToMove, $changedNodes); + $newParentNode->addChildWithSorting($nodeToMove); + } + GenericSortableTreeNode::processNewSortingRequest($nodeToMove, $newSorting, $changedNodes); } }