private function calculatePrevNext(Branch $siblings, HasNodeInterface $page, $loop)
 {
     $result = ['prev' => null, 'next' => null];
     // zero or one results (current page) means there is nowhere to navigate to
     if (1 >= sizeof($siblings->getChildren())) {
         return $result;
     }
     $current = null;
     foreach ($siblings->getChildren() as $item) {
         if ((string) $item->getRefId() === (string) $page->getId()) {
             $current = $item;
             break;
         }
     }
     if (null !== $current) {
         $result = ['prev' => $this->utility->getPreviousSibling($siblings, $current), 'next' => $this->utility->getNextSibling($siblings, $current)];
     }
     if ($loop) {
         $result['prev'] = $result['prev'] ?: $this->utility->getLastChild($siblings);
         $result['next'] = $result['next'] ?: $this->utility->getFirstChild($siblings);
     }
     return $result;
 }
 private function initNodeVersions()
 {
     if (null !== $this->nodeVersions) {
         return;
     }
     $results = $this->em->getRepository('KunstmaanNodeBundle:NodeVersion')->createQueryBuilder('nv')->select('nv.refEntityName', 'nv.refId', 'nv.id', 'n.internalName', 'nt.url', 'nt.lang', 'nt.title', 'n.id as nodeId')->innerJoin('nv.nodeTranslation', 'nt', Join::WITH, 'nt.publicNodeVersion = nv.id')->innerJoin('nt.node', 'n')->where('nt.online = 1')->andWhere('n.deleted = 0')->orderBy('n.lvl, nt.weight')->getQuery()->getResult(AbstractQuery::HYDRATE_ARRAY);
     foreach ($results as $item) {
         $id = $item['id'];
         $branch = new Branch($item['title'], $item['nodeId'], $item['url'], $item['lang'], $item['refId'], $item['refEntityName'], $item['internalName']);
         $this->nodeVersions[$branch->getRefName()][$branch->getRefId()] = $id;
         $this->branches[] = $branch;
         $this->refs[$id] = $branch->getRefId();
         $this->nodeRefs[$item['lang']][$branch->getNodeId()] = $branch->getRefId();
     }
 }
 /**
  * @param array $options
  *
  * @return mixed
  */
 private function getNodeChildren(array $options)
 {
     /** @noinspection PhpUnusedParameterInspection */
     $options = (new OptionsResolver())->setDefaults(['depth' => 1, 'refName' => null, 'parent' => null, 'lang' => $this->currentLocale->getCurrentLocale(), 'include_root' => false, 'include_hidden' => false, 'include_offline' => false, 'flatten' => false, 'limit' => 0])->setNormalizer('refName', function ($options, $value) {
         return $value ? (array) $value : [];
     })->setAllowedTypes('parent', ['null', Node::class])->setAllowedTypes('depth', 'integer')->setAllowedTypes('limit', 'integer')->setAllowedTypes('include_root', 'bool')->setAllowedTypes('include_hidden', 'bool')->setAllowedTypes('flatten', 'bool')->resolve($options);
     $qb = $this->nodeRepository->createQueryBuilder('node')->leftJoin('node.nodeTranslations', 'nt', Join::WITH, 'nt.node = node and nt.lang = :lang')->leftJoin('nt.publicNodeVersion', 'nv')->leftJoin('node.parent', 'parent')->select('parent.id as parentId', 'node.id', 'nt.title', 'nt.url', 'nt.lang', 'nv.refId', 'nv.refEntityName', 'node.internalName')->where('nt.lang = :lang')->andWhere('node.deleted = 0')->orderBy('node.lvl, nt.weight')->setParameter('lang', $options['lang']);
     if ($options['limit']) {
         $qb->setMaxResults($options['limit']);
     }
     if (false === $options['include_hidden']) {
         $qb->andWhere('node.hiddenFromNav = 0');
     }
     if (false === $options['include_offline']) {
         $qb->andWhere('nt.online = 1');
     }
     if ($options['refName']) {
         $qb->andWhere('node.refEntityName in (:refName)')->setParameter('refName', $options['refName']);
     }
     $level = 0;
     $nodeId = null;
     if ($options['parent']) {
         /** @var Node $parent */
         $parent = $options['parent'];
         $nodeId = $parent->getId();
         $level = $parent->getLevel();
         $qb->andWhere('node.lft >= :minLeft')->andWhere('node.rgt <= :maxRight')->setParameter('minLeft', $parent->getLeft())->setParameter('maxRight', $parent->getRight());
         if (false === $options['include_root']) {
             $qb->andWhere('node.id != :nodeId')->setParameter('nodeId', $nodeId);
         }
     }
     if ($options['depth']) {
         $qb->andWhere('node.lvl <= :maxLevel')->setParameter('maxLevel', $level + $options['depth']);
     }
     $children = $qb->getQuery()->getResult();
     $flatten = $options['flatten'];
     /** @noinspection PhpInternalEntityUsedInspection */
     return array_reduce($children, function (TreeBuilder $treeBuilder, $item) use($nodeId, $flatten) {
         $branch = new Branch($item['title'], $item['id'], $item['url'], $item['lang'], $item['refId'], $item['refEntityName'], $item['internalName']);
         if ($branch->getNodeId() === $nodeId) {
             $item['parentId'] = null;
         } elseif ($flatten) {
             $item['parentId'] = $nodeId;
         }
         return $treeBuilder->add($item['parentId'], $branch);
     }, new TreeBuilder())->getRoot();
 }