/**
  * @param ChangeSet $changeset
  * @return bool|object
  */
 public function applyChangeSet(ChangeSet $changeset)
 {
     $now = new \DateTime();
     if ($changeset->getChangeAt() == null || $changeset->getChangeAt()->diff($now)->invert) {
         return false;
     }
     if ($changeset->getAction() == LoggableListener::ACTION_CREATE && $changeset->getObjectId() != null) {
         throw new \Exception("changeSet invalid {$changeset->getId()}  create with object id");
     }
     if ($changeset->getAction() != LoggableListener::ACTION_CREATE && $changeset->getObjectId() == null) {
         throw new \Exception("changeSet invalid {$changeset->getId()}  no objectId found but no create Action");
     }
     $data = $changeset->getData();
     if ($changeset->getObjectId() == null) {
         //create a new one
         $r = new \ReflectionClass($changeset->getObjectClass());
         $entity = $r->newInstanceWithoutConstructor();
     } else {
         //edit
         $entity = $this->_em->find($changeset->getObjectClass(), $changeset->getObjectId());
     }
     if ($changeset->getAction() == LoggableListener::ACTION_REMOVE) {
         //very rudimental remove... dont care about sitdeffects
         $this->_em->remove($entity);
         $this->_em->remove($changeset);
         $this->_em->flush();
         return true;
     }
     $wrapped = new EntityWrapper($entity, $this->_em);
     $objectMeta = $wrapped->getMetadata();
     foreach ($data as $field => $value) {
         if ($objectMeta->isSingleValuedAssociation($field)) {
             $mapping = $objectMeta->getAssociationMapping($field);
             $value = $value ? $this->_em->getReference($mapping['targetEntity'], $value) : null;
         }
         if (property_exists($changeset->getObjectClass(), $field)) {
             $wrapped->setPropertyValue($field, $value);
         }
     }
     if ($changeset->getObjectId() == null) {
         //MANY_TO_ONE create new one
         foreach ($objectMeta->getAssociationMappings() as $associationMapping) {
             if ($associationMapping['type'] != \Doctrine\ORM\Mapping\ClassMetadata::MANY_TO_ONE) {
                 continue;
             }
             $one = $objectMeta->getReflectionProperty($associationMapping['fieldName'])->getValue($entity);
             if (array_key_exists('inversedBy', $associationMapping)) {
                 $field = $associationMapping['inversedBy'];
                 $associationMeta = $this->_em->getClassMetadata($associationMapping['targetEntity']);
                 $associationMeta->getReflectionProperty($field)->getValue($one)->add($entity);
             }
         }
     }
     $object = $wrapped->getObject();
     $object->removeScheduledChangeDate();
     $this->_em->persist($object);
     $this->_em->remove($changeset);
     $this->_em->flush();
     return $object;
 }
 /**
  * {@inheritDoc}
  */
 public function childCount($node = null, $direct = false)
 {
     $meta = $this->getClassMetadata();
     if (is_object($node)) {
         if (!$node instanceof $meta->name) {
             throw new InvalidArgumentException("Node is not related to this repository");
         }
         $wrapped = new EntityWrapper($node, $this->_em);
         if (!$wrapped->hasValidIdentifier()) {
             throw new InvalidArgumentException("Node is not managed by UnitOfWork");
         }
     }
     $qb = $this->getChildrenQueryBuilder($node, $direct);
     // We need to remove the ORDER BY DQL part since some vendors could throw an error
     // in count queries
     $dqlParts = $qb->getDQLParts();
     // We need to check first if there's an ORDER BY DQL part, because resetDQLPart doesn't
     // check if its internal array has an "orderby" index
     if (isset($dqlParts['orderBy'])) {
         $qb->resetDQLPart('orderBy');
     }
     $aliases = $qb->getRootAliases();
     $alias = $aliases[0];
     $qb->select('COUNT(' . $alias . ')');
     return (int) $qb->getQuery()->getSingleScalarResult();
 }
 /**
  * Get log entries
  * 
  * @access public
  * @param array $entities ,default is empty array
  * @param array $objectIds ,default is empty array
  * @param string $objectClass ,default is null
  * @param int $status ,default is null
  * @return array log entries array
  */
 public function getLogEntries($entities = array(), $objectIds = array(), $objectClass = null, $status = null)
 {
     $parameters = array();
     $queryBuilder = $this->createQueryBuilder("log");
     $queryBuilder->select("log")->addOrderBy('log.version', Criteria::DESC)->addOrderBy('log.id', Criteria::DESC);
     if (count($entities) > 0) {
         // assuming array of entities belong to them class
         $entity = reset($entities);
         $objectIds = array();
         $wrapped = new EntityWrapper($entity, $this->getEntityManager());
         $objectClass = $wrapped->getMetadata()->name;
         // collect entitites ids
         array_shift($entities);
         $objectIds[] = $wrapped->getIdentifier();
         foreach ($entities as $entity) {
             $wrapped = new EntityWrapper($entity, $this->getEntityManager());
             $objectIds[] = $wrapped->getIdentifier();
         }
     }
     if (!is_null($status)) {
         $parameters["objectStatus"] = $status;
         $queryBuilder->andWhere($queryBuilder->expr()->eq('log.objectStatus', ":objectStatus"));
     }
     if (!is_null($objectClass)) {
         $parameters["objectClass"] = $objectClass;
         $queryBuilder->andWhere($queryBuilder->expr()->eq('log.objectClass', ":objectClass"));
     }
     if (count($objectIds) > 0) {
         $parameters["objectIds"] = $objectIds;
         $queryBuilder->andWhere($queryBuilder->expr()->in('log.objectId', ":objectIds"));
     }
     $queryBuilder->setParameters($parameters);
     return $queryBuilder->getQuery()->getResult();
 }
 public function testSomeFunctions()
 {
     $test = new Article();
     $wrapped = new EntityWrapper($test, $this->em);
     $wrapped->populate(array('title' => 'test'));
     $this->assertEquals('test', $wrapped->getPropertyValue('title'));
     $this->assertFalse($wrapped->hasValidIdentifier());
 }
Example #5
0
 public function getLogEntriesQueryBuilder($entity)
 {
     $wrapped = new EntityWrapper($entity, $this->_em);
     $objectClass = $wrapped->getMetadata()->name;
     $objectId = $wrapped->getIdentifier();
     $qb = $this->createQueryBuilder('a')->where('a.objectId = :objectId AND a.objectClass = :objectClass')->orderBy('a.loggedAt', 'DESC')->setParameters(compact('objectId', 'objectClass'));
     return $qb;
 }
Example #6
0
 public function nullifyLogEntry($entity, $rootVersion)
 {
     $wrapped = new EntityWrapper($entity, $this->_em);
     $objectClass = $wrapped->getMetadata()->name;
     $objectId = $wrapped->getIdentifier();
     $logEntry = $this->findOneBy(compact('objectId', 'objectClass', 'rootVersion'));
     if ($logEntry) {
         $logEntry->setData(null);
         $this->getEntityManager()->flush($logEntry);
     }
 }
 /**
  * Get the query for loading of log entries
  *
  * @param object  $entity
  * @param integer $rootVersion
  *
  * @return Query
  */
 public function getLogEntriesQueryRoot($entity, $rootVersion = null)
 {
     $wrapped = new EntityWrapper($entity, $this->_em);
     $objectClass = $wrapped->getMetadata()->name;
     $meta = $this->getClassMetadata();
     $dql = "SELECT log FROM {$meta->name} log";
     $dql .= " WHERE log.objectId = :objectId";
     $dql .= " AND log.objectClass = :objectClass";
     $dql .= " AND log.rootVersion <= :rootVersion";
     $dql .= " ORDER BY log.version DESC";
     $objectId = $wrapped->getIdentifier();
     $q = $this->_em->createQuery($dql);
     $q->setParameters(compact('objectId', 'objectClass', 'rootVersion'));
     return $q;
 }
 /**
  * {@inheritDoc}
  */
 public function childCount($node = null, $direct = false)
 {
     $meta = $this->getClassMetadata();
     if (is_object($node)) {
         if (!$node instanceof $meta->name) {
             throw new InvalidArgumentException("Node is not related to this repository");
         }
         $wrapped = new EntityWrapper($node, $this->_em);
         if (!$wrapped->hasValidIdentifier()) {
             throw new InvalidArgumentException("Node is not managed by UnitOfWork");
         }
     }
     $qb = $this->getChildrenQueryBuilder($node, $direct);
     $aliases = $qb->getRootAliases();
     $alias = $aliases[0];
     $qb->select('COUNT(' . $alias . ')');
     return (int) $qb->getQuery()->getSingleScalarResult();
 }
Example #9
0
    /**
     * Reverts given $entity to $revision by
     * restoring all fields from that $revision.
     * After this operation you will need to
     * persist and flush the $entity.
     *
     * @param object $entity
     * @param integer $version
     * @throws \Gedmo\Exception\UnexpectedValueException
     * @return void
     */
    public function revert($entity, $version = 1)
    {
        $wrapped = new EntityWrapper($entity, $this->_em);
        $objectMeta = $wrapped->getMetadata();
        $objectClass = $objectMeta->name;
        //$objectMeta = $this->_em->getClassMetadata($objectClass);
        $meta = $this->getClassMetadata();
        $dql = "SELECT log FROM {$meta->name} log";
        $dql .= " WHERE log.objectId = :objectId";
        $dql .= " AND log.objectClass = :objectClass";
        $dql .= " AND log.version <= :version";
        $dql .= " ORDER BY log.version ASC";

        $objectId = $wrapped->getIdentifier();
        $q = $this->_em->createQuery($dql);
        $q->setParameters(compact('objectId', 'objectClass', 'version'));
        $logs = $q->getResult();

        if ($logs) {
            $config = $this->getLoggableListener()->getConfiguration($this->_em, $objectMeta->name);
            $fields = $config['versioned'];
            $filled = false;
            while (($log = array_pop($logs)) && !$filled) {
                if ($data = $log->getData()) {
                    foreach ($data as $field => $value) {
                        if (in_array($field, $fields)) {
                            if ($objectMeta->isSingleValuedAssociation($field)) {
                                $mapping = $objectMeta->getAssociationMapping($field);
                                $value = $value ? $this->_em->getReference($mapping['targetEntity'], $value) : null;
                            }
                            $wrapped->setPropertyValue($field, $value);
                            unset($fields[array_search($field, $fields)]);
                        }
                    }
                }
                $filled = count($fields) === 0;
            }
            if (count($fields)) {
                throw new \Gedmo\Exception\UnexpectedValueException('Cound not fully revert the entity to version: '.$version);
            }
        } else {
            throw new \Gedmo\Exception\UnexpectedValueException('Count not find any log entries under version: '.$version);
        }
    }
 /**
  * Loads all translations with all translatable
  * fields from the given entity
  *
  * @param object $entity Must implement Translatable
  * @return array list of translations in locale groups
  */
 public function findTranslations($entity)
 {
     $result = array();
     $wrapped = new EntityWrapper($entity, $this->_em);
     if ($wrapped->hasValidIdentifier()) {
         $entityId = $wrapped->getIdentifier();
         $entityClass = $wrapped->getMetadata()->name;
         $translationMeta = $this->getClassMetadata();
         // table inheritance support
         $qb = $this->_em->createQueryBuilder();
         $qb->select('trans.content, trans.field, trans.locale')->from($translationMeta->rootEntityName, 'trans')->where('trans.foreignKey = :entityId', 'trans.objectClass = :entityClass')->orderBy('trans.locale');
         $q = $qb->getQuery();
         $data = $q->execute(compact('entityId', 'entityClass'), Query::HYDRATE_ARRAY);
         if ($data && is_array($data) && count($data)) {
             foreach ($data as $row) {
                 $result[$row['locale']][$row['field']] = $row['content'];
             }
         }
     }
     return $result;
 }
 /**
  * {@inheritDoc}
  */
 public function getChildrenQueryBuilder($node = null, $direct = false, $sortByField = null, $direction = 'asc', $includeNode = false)
 {
     $meta = $this->getClassMetadata();
     $config = $this->listener->getConfiguration($this->_em, $meta->name);
     $separator = addcslashes($config['path_separator'], '%');
     $alias = 'materialized_path_entity';
     $path = $config['path'];
     $qb = $this->getQueryBuilder()->select($alias)->from($config['useObjectClass'], $alias);
     $expr = '';
     $includeNodeExpr = '';
     if (is_object($node) && $node instanceof $meta->name) {
         $node = new EntityWrapper($node, $this->_em);
         $nodePath = $node->getPropertyValue($path);
         $expr = $qb->expr()->andx()->add($qb->expr()->like($alias . '.' . $path, $qb->expr()->literal($nodePath . ($config['path_ends_with_separator'] ? '' : $separator) . '%')));
         if ($includeNode) {
             $includeNodeExpr = $qb->expr()->eq($alias . '.' . $path, $qb->expr()->literal($nodePath));
         } else {
             $expr->add($qb->expr()->neq($alias . '.' . $path, $qb->expr()->literal($nodePath)));
         }
         if ($direct) {
             $expr->add($qb->expr()->orx($qb->expr()->eq($alias . '.' . $config['level'], $qb->expr()->literal($node->getPropertyValue($config['level']))), $qb->expr()->eq($alias . '.' . $config['level'], $qb->expr()->literal($node->getPropertyValue($config['level']) + 1))));
         }
     } elseif ($direct) {
         $expr = $qb->expr()->not($qb->expr()->like($alias . '.' . $path, $qb->expr()->literal(($config['path_starts_with_separator'] ? $separator : '') . '%' . $separator . '%' . ($config['path_ends_with_separator'] ? $separator : ''))));
     }
     if ($expr) {
         $qb->where('(' . $expr . ')');
     }
     if ($includeNodeExpr) {
         $qb->orWhere('(' . $includeNodeExpr . ')');
     }
     $orderByField = is_null($sortByField) ? $alias . '.' . $config['path'] : $alias . '.' . $sortByField;
     $orderByDir = $direction === 'asc' ? 'asc' : 'desc';
     $qb->orderBy($orderByField, $orderByDir);
     return $qb;
 }
Example #12
0
 /**
  * Removes given $node from the tree and reparents its descendants
  *
  * @todo: may be improved, to issue single query on reparenting
  * @param object $node
  * @throws RuntimeException - if something fails in transaction
  * @return void
  */
 public function removeFromTree($node)
 {
     $meta = $this->getClassMetadata();
     if (!$node instanceof $meta->name) {
         throw new InvalidArgumentException("Node is not related to this repository");
     }
     $wrapped = new EntityWrapper($node, $this->_em);
     if (!$wrapped->hasValidIdentifier()) {
         throw new InvalidArgumentException("Node is not managed by UnitOfWork");
     }
     $config = $this->listener->getConfiguration($this->_em, $meta->name);
     $pk = $meta->getSingleIdentifierFieldName();
     $nodeId = $wrapped->getIdentifier();
     $parent = $wrapped->getPropertyValue($config['parent']);
     $dql = "SELECT node FROM {$config['useObjectClass']} node";
     $dql .= " WHERE node.{$config['parent']} = :node";
     $q = $this->_em->createQuery($dql);
     $q->setParameters(compact('node'));
     $nodesToReparent = $q->getResult();
     // process updates in transaction
     $this->_em->getConnection()->beginTransaction();
     try {
         foreach ($nodesToReparent as $nodeToReparent) {
             $id = $meta->getReflectionProperty($pk)->getValue($nodeToReparent);
             $meta->getReflectionProperty($config['parent'])->setValue($nodeToReparent, $parent);
             $dql = "UPDATE {$config['useObjectClass']} node";
             $dql .= " SET node.{$config['parent']} = :parent";
             $dql .= " WHERE node.{$pk} = :id";
             $q = $this->_em->createQuery($dql);
             $q->setParameters(compact('parent', 'id'));
             $q->getSingleScalarResult();
             $this->listener->getStrategy($this->_em, $meta->name)->updateNode($this->_em, $nodeToReparent, $node);
             $oid = spl_object_hash($nodeToReparent);
             $this->_em->getUnitOfWork()->setOriginalEntityProperty($oid, $config['parent'], $parent);
         }
         $dql = "DELETE {$config['useObjectClass']} node";
         $dql .= " WHERE node.{$pk} = :nodeId";
         $q = $this->_em->createQuery($dql);
         $q->setParameters(compact('nodeId'));
         $q->getSingleScalarResult();
         $this->_em->getConnection()->commit();
     } catch (\Exception $e) {
         $this->_em->close();
         $this->_em->getConnection()->rollback();
         throw new \Gedmo\Exception\RuntimeException('Transaction failed', null, $e);
     }
     // remove from identity map
     $this->_em->getUnitOfWork()->removeFromIdentityMap($node);
     $node = null;
 }
Example #13
0
    /**
     * Get hierarchy array of children followed by given $node
     *
     * @param object $node - from which node to start reordering the tree
     * @param boolean $direct - true to take only direct children
     * @param string $direction - sort direction : "ASC" or "DESC"
     * @return array $trees
     */
    public function childrenArrayHierarchy($node = null, $direct = false, $direction = "ASC")
    {
        $meta = $this->getClassMetadata();
        $config = $this->listener->getConfiguration($this->_em, $meta->name);

        if ($node !== null) {
            if ($node instanceof $meta->name) {
                $wrapped = new EntityWrapper($node, $this->_em);
                if (!$wrapped->hasValidIdentifier()) {
                    throw new InvalidArgumentException("Node is not managed by UnitOfWork");
                }
            }
        }

        // Gets the array of $node results.
        // It must be order by 'root' field
        $nodes = self::childrenQuery($node, $direct, 'root' , $direction)->getArrayResult();

        // Trees mapped
        $trees = array();
        $l = 0;

        if (count($nodes) > 0) {
            // Node Stack. Used to help building the hierarchy
            $stack = array();

            foreach ($nodes as $child) {
                $item = $child;

                $item['__children'] = array();

                // Number of stack items
                $l = count($stack);

                // Check if we're dealing with different levels
                while($l > 0 && $stack[$l - 1]['lvl'] >= $item['lvl']) {
                    array_pop($stack);
                    $l--;
                }

                // Stack is empty (we are inspecting the root)
                if ($l == 0) {
                    // Assigning the root child
                    $i = count($trees);
                    $trees[$i] = $item;
                    $stack[] = & $trees[$i];
                } else {
                    // Add child to parent
                    $i = count($stack[$l - 1]['__children']);
                    $stack[$l - 1]['__children'][$i] = $item;
                    $stack[] = & $stack[$l - 1]['__children'][$i];
                }
            }
        }
        return $trees;
    }
 /**
  * Get children from node
  *
  * @return Doctrine\ORM\QueryBuilder
  */
 public function getChildrenQueryBuilder($node = null, $direct = false, $sortByField = null, $direction = 'asc')
 {
     $meta = $this->getClassMetadata();
     $config = $this->listener->getConfiguration($this->_em, $meta->name);
     $separator = addcslashes($config['path_separator'], '%');
     $alias = 'materialized_path_entity';
     $path = $config['path'];
     $qb = $this->_em->createQueryBuilder($meta->name)->select($alias)->from($meta->name, $alias);
     if (is_object($node) && $node instanceof $meta->name) {
         $node = new EntityWrapper($node, $this->_em);
         $nodePath = $node->getPropertyValue($path);
         $expr = $qb->expr()->andx()->add($qb->expr()->like($alias . '.' . $path, $qb->expr()->literal($nodePath . '%')));
         $expr->add($qb->expr()->neq($alias . '.' . $path, $qb->expr()->literal($nodePath)));
         if ($direct) {
             $expr->add($qb->expr()->not($qb->expr()->like($alias . '.' . $path, $qb->expr()->literal($nodePath . '%' . $separator . '%' . $separator))));
         }
         $qb->where('(' . $expr . ')');
     } else {
         if ($direct) {
             $expr = $qb->expr()->not($qb->expr()->like($alias . '.' . $path, $qb->expr()->literal('%' . $separator . '%' . $separator . '%')));
             $qb->where('(' . $expr . ')');
         }
     }
     $orderByField = is_null($sortByField) ? $alias . '.' . $config['path'] : $alias . '.' . $sortByField;
     $orderByDir = $direction === 'asc' ? 'asc' : 'desc';
     $qb->orderBy($orderByField, $orderByDir);
     return $qb;
 }
 /**
  * Loads all translations with all translatable
  * fields from the given entity
  *
  * @param object $entity Must implement Translatable
  *
  * @return array list of translations in locale groups
  */
 public function findTranslations($entity)
 {
     $result = array();
     $wrapped = new EntityWrapper($entity, $this->em);
     if ($wrapped->hasValidIdentifier()) {
         if (is_object($entity)) {
             $entityClass = $entity instanceof Proxy ? get_parent_class($entity) : get_class($entity);
         } else {
             throw new InvalidArgumentException('Argument 1 passed to TranslationRepository::translate must be an object');
         }
         $reflectionClass = new \ReflectionClass($entityClass);
         $translationClass = $this->isPersonnalTranslationRecursive($reflectionClass)->class;
         $qb = $this->em->createQueryBuilder();
         $qb->select('trans.content, trans.field, trans.locale')->from($translationClass, 'trans')->where('trans.object = :object')->orderBy('trans.locale');
         $q = $qb->getQuery();
         $data = $q->execute(array('object' => $entity), Query::HYDRATE_ARRAY);
         if ($data && is_array($data) && count($data)) {
             foreach ($data as $row) {
                 $result[$row['locale']][$row['field']] = $row['content'];
             }
         }
     }
     return $result;
 }
 /**
  * Removes single node without touching children
  *
  * @internal
  *
  * @param EntityWrapper $wrapped
  */
 private function removeSingle(EntityWrapper $wrapped)
 {
     $meta = $this->getClassMetadata();
     $config = $this->listener->getConfiguration($this->getEntityManager(), $meta->name);
     $pk = $meta->getSingleIdentifierFieldName();
     $nodeId = $wrapped->getIdentifier();
     // prevent from deleting whole branch
     $qb = $this->getQueryBuilder();
     $qb->update($config['useObjectClass'], 'node')->set('node.' . $config['left'], 0)->set('node.' . $config['right'], 0);
     $qb->andWhere($qb->expr()->eq('node.' . $pk, ':id'));
     $qb->setParameter('id', $nodeId);
     $qb->getQuery()->getSingleScalarResult();
     // remove the node from database
     $qb = $this->getQueryBuilder();
     $qb->delete($config['useObjectClass'], 'node');
     $qb->andWhere($qb->expr()->eq('node.' . $pk, ':id'));
     $qb->setParameter('id', $nodeId);
     $qb->getQuery()->getSingleScalarResult();
     // remove from identity map
     $this->getEntityManager()->getUnitOfWork()->removeFromIdentityMap($wrapped->getObject());
 }
Example #17
0
 /**
  * @see getChildrenQueryBuilder
  */
 public function childrenWithTranslations($node = null, $locale = null, $direct = false, $sortByField = null, $direction = 'ASC', $includeNode = false, $start = null, $limit = null)
 {
     $meta = $this->getClassMetadata();
     $config = $this->listener->getConfiguration($this->_em, $meta->name);
     $qb = $this->getQueryBuilder();
     $qb->select('node', 't')->from($config['useObjectClass'], 'node')->leftJoin('node.translations', 't');
     if ($node !== null) {
         if ($node instanceof $meta->name) {
             $wrapped = new EntityWrapper($node, $this->_em);
             if (!$wrapped->hasValidIdentifier()) {
                 throw new InvalidArgumentException("Node is not managed by UnitOfWork");
             }
             if ($direct) {
                 $id = $wrapped->getIdentifier();
                 $qb->where($id === null ? $qb->expr()->isNull('node.' . $config['parent']) : $qb->expr()->eq('node.' . $config['parent'], is_string($id) ? $qb->expr()->literal($id) : $id));
             } else {
                 $left = $wrapped->getPropertyValue($config['left']);
                 $right = $wrapped->getPropertyValue($config['right']);
                 if ($left && $right) {
                     $qb->where($qb->expr()->lt('node.' . $config['right'], $right))->andWhere($qb->expr()->gt('node.' . $config['left'], $left));
                 }
             }
             if (isset($config['root'])) {
                 $rootId = $wrapped->getPropertyValue($config['root']);
                 $qb->andWhere($rootId === null ? $qb->expr()->isNull('node.' . $config['root']) : $qb->expr()->eq('node.' . $config['root'], is_string($rootId) ? $qb->expr()->literal($rootId) : $rootId));
             }
             if ($includeNode) {
                 $idField = $meta->getSingleIdentifierFieldName();
                 $qb->where('(' . $qb->getDqlPart('where') . ') OR node.' . $idField . ' = :rootNode');
                 $qb->setParameter('rootNode', $node);
             }
         } else {
             throw new \InvalidArgumentException("Node is not related to this repository");
         }
     } else {
         if ($direct) {
             $qb->where($qb->expr()->isNull('node.' . $config['parent']));
         }
     }
     if (!$sortByField) {
         $qb->orderBy('node.' . $config['left'], 'ASC');
     } elseif (is_array($sortByField)) {
         $fields = '';
         foreach ($sortByField as $field) {
             $fields .= 'node.' . $field . ',';
         }
         $fields = rtrim($fields, ',');
         $qb->orderBy($fields, $direction);
     } else {
         if ($meta->hasField($sortByField) && in_array(strtolower($direction), array('asc', 'desc'))) {
             $qb->orderBy('node.' . $sortByField, $direction);
         } else {
             throw new InvalidArgumentException("Invalid sort options specified: field - {$sortByField}, direction - {$direction}");
         }
     }
     if ($start) {
         $qb->setFirstResult($start);
     }
     if ($limit) {
         $qb->setMaxResults($limit);
     }
     return $this->setTranslatableHint($qb->getQuery(), $locale);
 }
 /**
  * {@inheritdoc}
  */
 public function persistAsNextSiblingOf(MenuItemInterface $node, MenuItemInterface $sibling)
 {
     $wrapped = new EntityWrapper($node, $this->_em);
     $meta = $this->getClassMetadata();
     $config = $this->treeListener->getConfiguration($this->_em, $meta->name);
     $wrappedSibling = new EntityWrapper($sibling, $this->_em);
     $newParent = $wrappedSibling->getPropertyValue($config['parent']);
     if (null === $newParent && isset($config['root'])) {
         throw new UnexpectedValueException('Cannot persist sibling for a root node, tree operation is not possible');
     }
     $node->sibling = $sibling;
     $sibling = $newParent;
     $wrapped->setPropertyValue($config['parent'], $sibling);
     $wrapped->setPropertyValue($config['left'], 0);
     $oid = spl_object_hash($node);
     $this->treeListener->getStrategy($this->_em, $meta->name)->setNodePosition($oid, 'NextSibling');
     $this->_em->persist($node);
     return $this;
 }
 /**
  * Removes single node without touching children
  *
  * @internal
  * @param EntityWrapper $wrapped
  * @return void
  */
 private function removeSingle(EntityWrapper $wrapped)
 {
     $meta = $this->getClassMetadata();
     $config = $this->listener->getConfiguration($this->_em, $meta->name);
     $pk = $meta->getSingleIdentifierFieldName();
     $nodeId = $wrapped->getIdentifier();
     // prevent from deleting whole branch
     $qb = $this->_em->createQueryBuilder();
     $qb->update($config['useObjectClass'], 'node')->set('node.' . $config['left'], 0)->set('node.' . $config['right'], 0)->where($nodeId === null ? $qb->expr()->isNull('node.' . $pk) : $qb->expr()->eq('node.' . $pk, is_string($nodeId) ? $qb->expr()->literal($nodeId) : $nodeId));
     $qb->getQuery()->getSingleScalarResult();
     // remove the node from database
     $qb = $this->_em->createQueryBuilder();
     $qb->delete($config['useObjectClass'], 'node')->where($nodeId === null ? $qb->expr()->isNull('node.' . $pk) : $qb->expr()->eq('node.' . $pk, is_string($nodeId) ? $qb->expr()->literal($nodeId) : $nodeId));
     $qb->getQuery()->getSingleScalarResult();
     // remove from identity map
     $this->_em->getUnitOfWork()->removeFromIdentityMap($wrapped->getObject());
 }
 /**
  * Retrieves the nested array or the html output
  *
  * @throws \Gedmo\Exception\InvalidArgumentException
  * @param object $node - from which node to start reordering the tree
  * @param boolean $direct - true to take only direct children
  * @param bool $html
  * @param array|null $options
  * @return array|string
  */
 public function childrenHierarchy($node = null, $direct = false, $html = false, array $options = null)
 {
     $meta = $this->getClassMetadata();
     $config = $this->listener->getConfiguration($this->_em, $meta->name);
     if ($node !== null) {
         if ($node instanceof $meta->name) {
             $wrapped = new EntityWrapper($node, $this->_em);
             if (!$wrapped->hasValidIdentifier()) {
                 throw new InvalidArgumentException("Node is not managed by UnitOfWork");
             }
         }
     }
     // Gets the array of $node results.
     // It must be order by 'root' field
     $nodes = self::childrenQuery($node, $direct, 'root', 'ASC')->getArrayResult();
     return $this->buildTree($nodes, $html, $options);
 }
 /**
  * Revert a Entity identified by $objectId and $objectClass to a specific $version
  * @param               $objectId
  * @param               $objectClass
  * @param               $version
  * @param EntityWrapper $wrapped
  * @param null          $softDeleteDateFieldName
  * @param bool          $deleteHistory if true, the revert will also delete all log entries since the reverted one
  * @param bool          $logRevert if logRevert is true, the revert will be logged
  */
 public function revertBy($objectId, $objectClass, $version, EntityWrapper $wrapped, $softDeleteDateFieldName = null, $deleteHistory = true, $logRevert = false)
 {
     $logs = $this->findLogs($objectId, $objectClass, $version);
     if (!$logs) {
         throw new \Gedmo\Exception\UnexpectedValueException('Could not find any log entries under version: ' . $version);
     }
     if (!$logRevert) {
         $this->getLoggableListener()->setEnabled(false);
     }
     while ($log = array_pop($logs)) {
         $action = $log->getAction();
         if ($action === 'create') {
             if (!$softDeleteDateFieldName) {
                 throw new \Gedmo\Exception\UnexpectedValueException('Cant revert to create: you have to use softdeletable to use this feature');
             }
             $wrapped->setPropertyValue($softDeleteDateFieldName, new \DateTime());
         } else {
             if ($action === 'remove') {
                 if (!$softDeleteDateFieldName) {
                     throw new \Gedmo\Exception\UnexpectedValueException('Cant revert to create: you have to use softdeletable to use this feature');
                 }
                 $wrapped->setPropertyValue($softDeleteDateFieldName, null);
             } else {
                 $this->revertObjectBySingleLog($log, $wrapped);
             }
         }
         $this->_em->flush();
         if ($deleteHistory) {
             if ($logRevert) {
                 $this->getLoggableListener()->setEnabled(false);
             }
             $this->_em->remove($log);
             if ($logRevert) {
                 $this->getLoggableListener()->setEnabled(true);
             }
         }
     }
     if (!$logRevert) {
         $this->getLoggableListener()->setEnabled(true);
     }
 }
 /**
  * Removes single node without touching children
  *
  * @internal
  * @param EntityWrapper $wrapped
  * @return void
  */
 private function removeSingle(EntityWrapper $wrapped)
 {
     $meta = $this->getClassMetadata();
     $config = $this->listener->getConfiguration($this->_em, $meta->name);
     $pk = $meta->getSingleIdentifierFieldName();
     $nodeId = $wrapped->getIdentifier();
     // prevent from deleting whole branch
     $dql = "UPDATE {$config['useObjectClass']} node";
     $dql .= ' SET node.' . $config['left'] . ' = 0,';
     $dql .= ' node.' . $config['right'] . ' = 0';
     $dql .= ' WHERE node.' . $pk . ' = ' . $nodeId;
     $this->_em->createQuery($dql)->getSingleScalarResult();
     // remove the node from database
     $dql = "DELETE {$config['useObjectClass']} node";
     $dql .= " WHERE node.{$pk} = {$nodeId}";
     $this->_em->createQuery($dql)->getSingleScalarResult();
     // remove from identity map
     $this->_em->getUnitOfWork()->removeFromIdentityMap($wrapped->getObject());
 }