/** * Accomplishes moving of nodes between different trees. * Used by the move* methods if the root values of the two nodes are * different. * * NOTE: This method does not wrap its database queries in a transaction. * This should be done before invoking this code. * * @param NodeWrapper $node * @param int $newLeftValue * @param string $moveType */ protected function moveBetweenTrees(NodeWrapper $node, $newLeftValue, $moveType) { if (!$this->hasManyRoots()) { // @codeCoverageIgnoreStart throw new \BadMethodCallException(sprintf('%s::%s is only supported on multiple root trees', __CLASS__, __METHOD__)); // @codeCoverageIgnoreEnd } $em = $this->getManager()->getEntityManager(); $lftField = $this->getLeftFieldName(); $rgtField = $this->getRightFieldName(); $rootField = $this->getRootFieldName(); $newRoot = $node->getRootValue(); $oldRoot = $this->getRootValue(); $oldLft = $this->getLeftValue(); $oldRgt = $this->getRightValue(); // Prepare target tree for insertion, make room $this->shiftRLRange($newLeftValue, 0, $oldRgt - $oldLft + 1, $newRoot); // Set new position and root of this node $this->setLeftValue($newLeftValue); $this->setRightValue($newLeftValue + ($oldRgt - $oldLft)); $this->setRootValue($newRoot); $em->persist($this->getNode()); $em->flush(); // Relocate descendants of the node $diff = $this->getLeftValue() - $oldLft; //echo "\nRelocating: oldLft=$oldLft, oldRgt=$oldRgt, diff=$diff, oldRoot=$oldRoot, newRoot=$newRoot\n"; $qb = $em->createQueryBuilder()->update(get_class($this->getNode()), 'n')->set("n.{$lftField}", "n.{$lftField} + ?1")->setParameter(1, $diff)->set("n.{$rgtField}", "n.{$rgtField} + ?2")->setParameter(2, $diff)->set("n.{$rootField}", "?3")->setParameter(3, $newRoot)->where("n.{$lftField} > ?4")->setParameter(4, $oldLft)->andWhere("n.{$rgtField} < ?5")->setParameter(5, $oldRgt)->andWhere("n.{$rootField} = ?6")->setParameter(6, $oldRoot); $qb->getQuery()->execute(); $this->getManager()->updateValues($oldLft, $oldRgt, $diff, $oldRoot, $newRoot); // Close gap in old tree $first = $oldRgt + 1; $delta = $oldLft - $oldRgt - 1; $this->shiftRLRange($first, 0, $delta, $oldRoot); }
/** * Accomplishes moving of nodes between different trees. * Used by the move* methods if the root values of the two nodes are * different. * * NOTE: This method does not wrap its database queries in a transaction. * This should be done before invoking this code. * * @param NodeWrapper $node * @param int $newLeftValue * @param string $moveType */ protected function moveBetweenTrees(NodeWrapper $node, $newLeftValue, $moveType) { $em = $this->getManager()->getEntityManager(); $lftField = $this->getLeftFieldName(); $rgtField = $this->getRightFieldName(); $rootField = $this->getRootFieldName(); $newRoot = $node->getRootValue(); $oldRoot = $this->getRootValue(); $oldLft = $this->getLeftValue(); $oldRgt = $this->getRightValue(); // Prepare target tree for insertion, make room $this->shiftRLRange($newLeftValue, 0, $oldRgt - $oldLft + 1, $newRoot); // Set new position and root of this node $this->setLeftValue($newLeftValue); $this->setRightValue($newLeftValue + ($oldRgt - $oldLft)); $this->setRootValue($newRoot); $em->persist($this->getNode()); $em->flush(); // Relocate descendants of the node $diff = $this->getLeftValue() - $oldLft; //echo "\nRelocating: oldLft=$oldLft, oldRgt=$oldRgt, diff=$diff, oldRoot=$oldRoot, newRoot=$newRoot\n"; $qb = $em->createQueryBuilder()->update(get_class($this->getNode()), 'n')->set("n.{$lftField}", "n.{$lftField} + ?1")->setParameter(1, $diff)->set("n.{$rgtField}", "n.{$rgtField} + ?2")->setParameter(2, $diff)->set("n.{$rootField}", "?3")->setParameter(3, $newRoot)->where("n.{$lftField} > ?4")->setParameter(4, $oldLft)->andWhere("n.{$rgtField} < ?5")->setParameter(5, $oldRgt)->andWhere("n.{$rootField} = ?6")->setParameter(6, $oldRoot); $qb->getQuery()->execute(); $this->getManager()->updateValues($oldLft, $oldRgt, $diff, $oldRoot, $newRoot); // Close gap in old tree $first = $oldRgt + 1; $delta = $oldLft - $oldRgt - 1; $this->shiftRLRange($first, 0, $delta, $oldRoot); }