/** * Sets the index of this node * * NOTE: This method is meant for internal use and must only be used by other nodes. * * @param integer $index The new index * @return void */ public function setIndex($index) { if (!$this->isNodeDataMatchingContext()) { $this->materializeNodeData(); } if ($this->getIndex() === $index) { return; } $this->nodeData->setIndex($index); $this->context->getFirstLevelNodeCache()->flush(); $this->emitNodeUpdated($this); }
/** * @test */ public function theIndexCanBeSetAndRetrieved() { $this->nodeData->setIndex(2); $this->assertEquals(2, $this->nodeData->getIndex()); }
/** * Assigns an index to the given node which reflects the specified position. * If the position is "before" or "after", an index will be chosen which makes * the given node the previous or next node of the given reference node. * If the position "last" is specified, an index higher than any existing index * will be chosen. * * If no free index is available between two nodes (for "before" and "after"), * the whole index of the current node level will be renumbered. * * @param NodeData $node The node to set the new index for * @param integer $position The position the new index should reflect, must be one of the POSITION_* constants * @param NodeInterface $referenceNode The reference node. Mandatory for POSITION_BEFORE and POSITION_AFTER * @return void * @throws \InvalidArgumentException */ public function setNewIndex(NodeData $node, $position, NodeInterface $referenceNode = null) { $parentPath = $node->getParentPath(); switch ($position) { case self::POSITION_BEFORE: if ($referenceNode === null) { throw new \InvalidArgumentException('The reference node must be specified for POSITION_BEFORE.', 1317198857); } $referenceIndex = $referenceNode->getIndex(); $nextLowerIndex = $this->findNextLowerIndex($parentPath, $referenceIndex); if ($nextLowerIndex === null) { // FIXME: $nextLowerIndex returns 0 and not NULL in case no lower index is found. So this case seems to be // never executed. We need to check that again! $newIndex = (int) round($referenceIndex / 2); } elseif ($nextLowerIndex < $referenceIndex - 1) { // there is free space left between $referenceNode and preceding sibling. $newIndex = (int) round($nextLowerIndex + ($referenceIndex - $nextLowerIndex) / 2); } else { // there is no free space left between $referenceNode and following sibling -> we have to make room! $this->openIndexSpace($parentPath, $referenceIndex); $referenceIndex = $referenceNode->getIndex(); $nextLowerIndex = $this->findNextLowerIndex($parentPath, $referenceIndex); if ($nextLowerIndex === null) { $newIndex = (int) round($referenceIndex / 2); } else { $newIndex = (int) round($nextLowerIndex + ($referenceIndex - $nextLowerIndex) / 2); } } break; case self::POSITION_AFTER: if ($referenceNode === null) { throw new \InvalidArgumentException('The reference node must be specified for POSITION_AFTER.', 1317198858); } $referenceIndex = $referenceNode->getIndex(); $nextHigherIndex = $this->findNextHigherIndex($parentPath, $referenceIndex); if ($nextHigherIndex === null) { // $referenceNode is last node, so we can safely add an index at the end by incrementing the reference index. $newIndex = $referenceIndex + 100; $this->setHighestIndexInParentPath($parentPath, $newIndex); } elseif ($nextHigherIndex > $referenceIndex + 1) { // $referenceNode is not last node, but there is free space left between $referenceNode and following sibling. $newIndex = (int) round($referenceIndex + ($nextHigherIndex - $referenceIndex) / 2); } else { // $referenceNode is not last node, and no free space is left -> we have to make room after the reference node! $this->openIndexSpace($parentPath, $referenceIndex + 1); $nextHigherIndex = $this->findNextHigherIndex($parentPath, $referenceIndex); if ($nextHigherIndex === null) { $newIndex = $referenceIndex + 100; $this->setHighestIndexInParentPath($parentPath, $newIndex); } else { $newIndex = (int) round($referenceIndex + ($nextHigherIndex - $referenceIndex) / 2); } } break; case self::POSITION_LAST: $nextFreeIndex = $this->findNextFreeIndexInParentPath($parentPath); $newIndex = $nextFreeIndex; break; default: throw new \InvalidArgumentException('Invalid position for new node index given.', 1329729088); } $node->setIndex($newIndex); }