/** * @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()); }
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; }
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(); }
/** * 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; }
/** * 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; }
/** * 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()); }
/** * @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()); }