@param  NodeInterface $node
@param  int $path_size
@param  int $max_depth
@param  int $start_pos

@return int[] int tuple containing max_depth and start_pos
338140
private function dfsLongestRepetition(NodeInterface $node, int $path_size, array $slice, $overlap = false): array
    {
        if ($node instanceof LeafNode && $slice[1] < $path_size - $node->getEdgeSize()) {
            $slice = [ $node->getSuffixIdx(), $path_size - $node->getEdgeSize() ];
        } else {
            $prev_slice = $slice;
            foreach ($node->getChildren() as $child_node) {
                $slice = $this->dfsLongestRepetition(
                    $child_node,
                    $path_size + $child_node->getEdgeSize(),
                    $slice,
                    $overlap
                );
            }
            if (!$overlap && $slice[1] > $prev_slice[1] && $node instanceof InternalNode
                && $path_size > $node->getMaxSuffixIdx() - $node->getMinSuffixIdx()
            ) { // prevent overlap when not allowed
                $slice = $prev_slice;
            }
        }

        return $slice;
    }
457954
protected function generatePath(TreeNodeInterface $node, $parameters)
    {
        if ($this->requestContext->getParameter('_preview') || isset($parameters['_preview'])) {
            return $this->generatePreviewPath($node, $parameters);
        }

        $pathGenerator = new PathGenerator();
        $path = $pathGenerator->generatePath($node, $parameters);

        if ($path === '') {
            return $path;
        }

        $path = $this->generatePathPrefix($path, $node, $parameters);
        $path = $this->generatePathSuffix($path, $node, $parameters);
        $path = $this->generateQuery($path, $node, $parameters);

        return $path;
    }
205166
public function getNodeCampNode(NodeInterface $node) {
    $camp = NULL;
    switch ($node->bundle()) {
      case 'camp':
        $camp = $node;
        break;

      case 'landing_page':
        $camp = $this->getLandingPageCampNode($node);
        break;
    }

    return $camp;
  }
452687
public function discardNode(NodeInterface $node)
    {
        $nodes = [$node];
        $nodeType = $node->getNodeType();

        if ($nodeType->isOfType('Neos.Neos:Document') || $nodeType->hasConfiguration('childNodes')) {
            $nodes = array_filter(
                array_merge($nodes, $this->collectAllContentChildNodes($node)),
                function ($possiblyPublishableNode) use ($node) {
                    return $possiblyPublishableNode->getWorkspace()->getName() === $node->getWorkspace()->getName();
                }
            );
        }

        $this->discardNodes($nodes);
    }
729993
private function collectNodes(NodeInterface $node, array $visited_nodes): array
    {
        if (in_array($node, $visited_nodes, true)) {
            return $visited_nodes;
        }

        $visited_nodes[] = $node;
        foreach ($node->getChildren() as $child) {
            $visited_nodes = $this->collectNodes($child, $visited_nodes);
        }

        return $visited_nodes;
    }
581337
public static function Create( $context, $node )
	{
		if ( is_a( $node, __CLASS__ ) )
		{
			/**
			 * @var PathStep $res
			 */
			$res = $node;
			return $res;
		}

		if ( $node instanceof PathExprNode )
		{
			/**
			 * @var PathExprNode $pathExpr
			 */
			$pathExpr = $node;
			return $pathExpr->FirstStep;
		}

		return PathStep::fromNode( AbstractNode::Create( $context, $node ) );
	}
1096032
protected function getNodePosition(ReadNodeInterface $node, $tree)
    {
        $position = $node->getOrder();
        while (array_key_exists($position, $tree)) {
            $position++;
        }

        return $position;
    }
604517
private function getSiblingNode(NodeInterface $node, $previous = false)
    {
        $parentNode = $node->getParent();
        $children = $parentNode->getNodes();
        $previousNode = null;

        while ($child = current($children)) {
            if ($child->getPath() === $node->getPath()) {
                return $previous ? $previousNode : next($children);
            }

            $previousNode = $child;
            next($children);
        }

        throw new \RuntimeException(
            sprintf(
                'Could not find node with path "%s" as a child of "%s". This should not happen',
                $node->getPath(),
                $parentNode->getPath()
            )
        );
    }
1239614
protected function parseNodeProperties(NodeInterface $node)
    {
        $properties = [];

        // Run through all node properties
        foreach ($node->getProperties() as $name => $property) {
            // Skip the node type
            if ($name === Node::TYPE) {
                continue;
            }

            // Initialize the property (if necessary)
            $this->initializeNodeProperty($name, $properties);

            // Parse and process the property value
            $this->processNodeProperty($name, $this->parse($property), $properties);
        }

        return $properties;
    }
208454
public static function getBranchesList(NodeInterface $node) {
    $branches_list = [
      'branch' => [],
      'camp' => [],
    ];

    if (!\Drupal::hasService('session_instance.manager')) {
      return $branches_list;
    }

    $locations = \Drupal::service('session_instance.manager')
      ->getLocationsByClassNode($node);
    foreach ($locations as $location) {
      if (!isset($branches_list[$location->bundle()][$location->id()])) {
        $branches_list[$location->bundle()][$location->id()] = $location->title->value;
      }
    }

    return $branches_list;
  }
929897
private function transferChildren(
        NodeInterface $node,
        array &$node_map = [],
        array &$lazy_links = [],
        int $path_size = 0
    ): array {
        $children = [];
        $suffix_min = -1;
        $suffix_max = $suffix_min;
        foreach ($node->children as $edge => $child_node) {
            if ($child_node instanceof LeafNode) {
                $new_node = new Leaf(
                    $child_node->start,
                    $child_node->end,
                    $this->length - ($path_size + $child_node->getEdgeSize()) + 1
                );
                if ($suffix_min === -1) {
                    $suffix_min = $new_node->getSuffixIdx();
                    $suffix_max = $suffix_min;
                } else {
                    $suffix_min = min($suffix_min, $new_node->getSuffixIdx());
                    $suffix_max = max($suffix_max, $new_node->getSuffixIdx());
                }
            } else {
                list($grand_children, $smin, $smax) = $this->transferChildren(
                    $child_node,
                    $node_map,
                    $lazy_links,
                    $path_size + $child_node->getEdgeSize()
                );
                $suffix_node = null;
                if ($child_node->suffix_link !== null) {
                    $suffix_hash = (string)$child_node->suffix_link;
                    $suffix_node = isset($node_map[$suffix_hash]) ? $node_map[$suffix_hash] : null;
                }
                $new_node = new Internal(
                    $child_node->start,
                    $child_node->end,
                    $smin,
                    $smax,
                    $grand_children,
                    $suffix_node
                );
                if ($suffix_node === null && $child_node->suffix_link !== null) {
                    $lazy_links[$suffix_hash] = $new_node;
                }
                $child_hash = (string)$child_node;
                if (isset($lazy_links[$child_hash])) {
                    // todo: find out way to prevent mutating node state here, need to get the new node ref
                    // into the proper place within the new tree
                    $lazy_links[$child_hash]->withSuffixLink($new_node);
                }
                if ($suffix_min === -1) {
                    $suffix_min = $new_node->getMinSuffixIdx();
                    $suffix_max = $new_node->getMaxSuffixIdx();
                } else {
                    $suffix_min = min($suffix_min, $new_node->getMinSuffixIdx());
                    $suffix_max = max($suffix_max, $new_node->getMaxSuffixIdx());
                }
                $node_map[$child_hash] = $new_node;
            }
            $children[$edge] = $new_node;
        }

        return [ $children, $suffix_min, $suffix_max ];
    }
775551
public function move(Node\NodeInterface $node, $pos, $levelDiff)
	{
		// Current node's interval
		$left = $node->getLeftValue();
		$right = $node->getRightValue();
		
		// How big is the node
		$spaceUsed = $right - $left + 1;
		
		// Tells for how much index the node will be moved
		$moveA = 0;
		
		// Tells for how much index the nodes between the node's current and 
		// future position will be moved
		$moveB = 0;
		
		// Tells the interval for indeces to be moved which are not inside the 
		// node interval (usually $a <= $b)
		$a = $b = 0;
		
		// Move to the right
		if ($pos > $left) {
			$a = $right + 1;
			$b = $pos - 1;
			$moveA = $pos - $left - $spaceUsed;
			$moveB = - $spaceUsed;
			
		// Move to the left
		} else {
			$a = $pos;
			$b = $left - 1;
			$moveA = $pos - $left;
			$moveB = $spaceUsed;
		}
		
		// There is nothing to move
		if ($moveA == 0 && $levelDiff == 0) {
			return;
		}
		
		foreach ($this->array as $item) {
			/* @var $item Node\NodeInterface */
			$itemLeft = $item->getLeftValue();
			$itemRight = $item->getRightValue();
			
			// Children of the page being moved
			if (self::isBetween($itemLeft, $left, $right)) {
				
				if ( ! self::isBetween($itemRight, $left, $right)) {
					throw new Exception\InvalidStructure("Node $item left index is between $node index but the right isn't");
				}

				$this->moveNode($item, $moveA, $moveA, $levelDiff);

//				$item->moveLeftValue($moveA);
//				$item->moveRightValue($moveA);
//				$item->moveLevel($levelDiff);
				continue;
			}

			// Left index matches the interval
			if (self::isBetween($itemLeft, $a, $b)) {
				$this->moveNode($item, $moveB, 0, 0);
//				$item->moveLeftValue($moveB);
			}
			
			// Right index matches the interval
			if (self::isBetween($itemRight, $a, $b)) {
				$this->moveNode($item, 0, $moveB, 0);
//				$item->moveRightValue($moveB);
			}
		}
	}
872138
public function getPropertiesArray(NodeInterface $node)
    {
        $properties = [];
        foreach ($node->getNodeType()->getProperties() as $propertyName => $propertyConfiguration) {
            if ($propertyName[0] === '_' && $propertyName[1] === '_') {
                // skip fully-private properties
                continue;
            }

            $properties[$propertyName] = $this->getProperty($node, $propertyName);
        }

        return $properties;
    }
203184
public function toFlat($node, $sep = ' > ', $path = '')
    {
        $els = [];

        foreach ($node as $id => $opts) {
            $els[$opts['id']] = $path . $opts['name'];
            if (isset($opts['__children']) && \is_array($opts['__children']) && \count($opts['__children'])) {
                $r = $this->toFlat($opts['__children'], $sep, $path . $opts['name'] . $sep);
                foreach ($r as $r_id => $title) {
                    $els[$r_id] = $title;
                }
            }
        }

        return $els;
    }
422852
protected function getChildren(ReadNodeInterface $node, $list)
    {
        $children = array();

        if (!empty($list[$node->getNodeId()]) && is_array($list[$node->getNodeId()])) {
            foreach ($list[$node->getNodeId()] as $child) {
                $position = $this->getNodePosition($child, $children);
                $children[$position] = $this->createTree($child, $list);
            }
        }

        $children = $this->sortArray($children);

        return $children;
    }
278106
public function setChildNodesByPathAndNodeTypeFilter($path, $nodeTypeFilter, array $nodes)
    {
        if (!isset($this->childNodesByPathAndNodeTypeFilter[$path])) {
            $this->childNodesByPathAndNodeTypeFilter[$path] = [];
        }

        foreach ($nodes as $node) {
            /** @var NodeInterface $node */
            $this->nodesByPath[$node->getPath()] = $node;
            $this->nodesByIdentifier[$node->getIdentifier()] = $node;
        }

        $this->childNodesByPathAndNodeTypeFilter[$path][$nodeTypeFilter] = $nodes;
    }
31805
public function getInstanceNodes(TreeNodeInterface $node)
    {
        $instanceNodes = [];
        foreach ($this->getAll() as $tree) {
            $instanceNodes = array_merge($instanceNodes, $tree->getInstances($node));
        }

        return $instanceNodes;
    }