/**
  * Returns a QueryBuilder to grab the siblings of the given node
  *
  * @param \DoctrineExtensions\Hierarchical\MaterializedPath\MaterializedPathNodeInfo $node
  * @return \Doctrine\ORM\QueryBuilder
  */
 public function getSiblingQueryBuilder(MaterializedPathNodeInfo $node)
 {
     $qb = $this->getBaseQueryBuilder();
     $expr = $qb->expr();
     $andX = $expr->andX();
     $andX->add($expr->eq('e.' . $node->getDepthFieldName(), $node->getDepth()));
     if ($node->getDepth() > 1) {
         $parentPath = PathHelper::getBasePath($node, $node->getPath(), $node->getDepth() - 1);
         $pathInterval = PathHelper::getChildrenPathInterval($node, $parentPath);
         $andX->add($expr->between('e.' . $node->getPathFieldName(), $expr->literal($pathInterval[0]), $expr->literal($pathInterval[1])));
     }
     $qb->where($andX);
     return $qb;
 }
 /**
  * Returns the base path of another path up to the specified depth
  *
  * @param string $path
  * @param string $depth
  * @return string
  */
 protected function _getBasePath($path, $depth)
 {
     return PathHelper::getBasePath($this, $path, $depth);
 }
 public function deleteQuerySet($qb, $knownChildren = false)
 {
     if ($knownChildren) {
         $batch = 20;
         $i = 0;
         $iterableResult = $qb->getQuery()->iterate();
         while (($row = $iterableResult->next()) !== false) {
             $this->em->remove($row[0]);
             if ($i++ % $batch == 0) {
                 $this->em->flush();
                 $this->em->clear();
             }
         }
         $this->em->flush();
         $this->em->clear();
         return;
     }
     $expr = $qb->expr();
     $qb->orderBy('e.' . $this->getDepthFieldName())->addOrderBy('e.' . $this->getPathFieldName());
     $removed = array();
     foreach ($qb->getQuery()->getResult() as $node) {
         $node = $this->getNode($node);
         $found = false;
         $range = array_slice(range(1, strlen($node->getPath()) / $this->getStepLength()), 0, -1);
         foreach ($range as $depth) {
             $path = PathHelper::getBasePath($node, $node->getPath(), $depth);
             if (isset($removed[$path])) {
                 // already removing a parent of this node
                 $found = true;
                 break;
             }
         }
         if (!$found) {
             $removed[$node->getPath()] = $node;
         }
     }
     $parents = array();
     $toRemove = array();
     foreach ($removed as $path => $node) {
         $parentPath = PathHelper::getBasePath($node, $node->getPath(), $node->getDepth() - 1);
         if ($parentPath) {
             if (!isset($parents[$parentPath])) {
                 $parents[$parentPath] = $node->getParent(true);
             }
             $parent = $parents[$parentPath];
             if ($parent && $parent->getNumberOfChildren() > 0) {
                 $parent->setValue($this->getNumChildrenFieldName(), $parent->getNumberOfChildren() - 1);
             }
         }
         if (!$node->isLeaf()) {
             $toRemove[] = $expr->like('e.' . $this->getPathFieldName(), $expr->literal($node->getPath() . '%'));
         } else {
             $toRemove[] = $expr->eq('e.' . $this->getPathFieldName(), $expr->literal($node->getPath()));
         }
     }
     if ($toRemove) {
         $orX = $expr->orX();
         $orX->addMultiple($toRemove);
         $qb->where($orX);
         $this->deleteQuerySet($qb, true);
     }
 }