public function getLast($id){
     $meta = $this->getClassMetadata();
     $config = $this->listener->getConfiguration($this->_em, $meta->name);
     $qb = $this->_em->createQueryBuilder();
     $qb->select('st')
         ->from($meta->name, 'st')
         ->orderBy('st.'.$config['status_field'], 'DESC')
         ->setMaxResults(1);
     $q = $qb->getQuery();
     return $q->getSingleResult();
 }
Beispiel #2
0
 /**
  * Shift range of right and left values on tree
  * depending on tree level diference also
  *
  * @param EntityManager $em
  * @param string $class
  * @param integer $first
  * @param integer $last
  * @param integer $delta
  * @param integer $rootId
  * @param integer $destRootId
  * @param integer $levelDelta
  * @return void
  */
 public function shiftRangeRL(EntityManager $em, $class, $first, $last, $delta, $rootId = null, $destRootId = null, $levelDelta = null)
 {
     $meta = $em->getClassMetadata($class);
     $config = $this->listener->getConfiguration($em, $class);
     $sign = $delta >= 0 ? ' + ' : ' - ';
     $absDelta = abs($delta);
     $levelSign = $levelDelta >= 0 ? ' + ' : ' - ';
     $absLevelDelta = abs($levelDelta);
     $dql = "UPDATE {$meta->name} node";
     $dql .= " SET node.{$config['left']} = node.{$config['left']} {$sign} {$absDelta}";
     $dql .= ", node.{$config['right']} = node.{$config['right']} {$sign} {$absDelta}";
     if (isset($config['root'])) {
         $dql .= ", node.{$config['root']} = {$destRootId}";
     }
     if (isset($config['level'])) {
         $dql .= ", node.{$config['level']} = node.{$config['level']} {$levelSign} {$absLevelDelta}";
     }
     $dql .= " WHERE node.{$config['left']} >= {$first}";
     $dql .= " AND node.{$config['right']} <= {$last}";
     if (isset($config['root'])) {
         $dql .= " AND node.{$config['root']} = {$rootId}";
     }
     $q = $em->createQuery($dql);
     $q->getSingleScalarResult();
     // update in memory nodes increases performance, saves some IO
     foreach ($em->getUnitOfWork()->getIdentityMap() as $className => $nodes) {
         // for inheritance mapped classes, only root is always in the identity map
         if ($className !== $meta->rootEntityName) {
             continue;
         }
         foreach ($nodes as $node) {
             if ($node instanceof Proxy && !$node->__isInitialized__) {
                 continue;
             }
             $left = $meta->getReflectionProperty($config['left'])->getValue($node);
             $right = $meta->getReflectionProperty($config['right'])->getValue($node);
             $root = isset($config['root']) ? $meta->getReflectionProperty($config['root'])->getValue($node) : null;
             if ($root === $rootId && $left >= $first && $right <= $last) {
                 $oid = spl_object_hash($node);
                 $uow = $em->getUnitOfWork();
                 $meta->getReflectionProperty($config['left'])->setValue($node, $left + $delta);
                 $uow->setOriginalEntityProperty($oid, $config['left'], $left + $delta);
                 $meta->getReflectionProperty($config['right'])->setValue($node, $right + $delta);
                 $uow->setOriginalEntityProperty($oid, $config['right'], $right + $delta);
                 if (isset($config['root'])) {
                     $meta->getReflectionProperty($config['root'])->setValue($node, $destRootId);
                     $uow->setOriginalEntityProperty($oid, $config['root'], $destRootId);
                 }
                 if (isset($config['level'])) {
                     $level = $meta->getReflectionProperty($config['level'])->getValue($node);
                     $meta->getReflectionProperty($config['level'])->setValue($node, $level + $levelDelta);
                     $uow->setOriginalEntityProperty($oid, $config['level'], $level + $levelDelta);
                 }
             }
         }
     }
 }
Beispiel #3
0
 /**
  * Update node and closures
  *
  * @param EntityManager $em
  * @param object $node
  * @param object $oldParent
  */
 public function updateNode(EntityManager $em, $node, $oldParent)
 {
     $wrapped = AbstractWrapper::wrap($node, $em);
     $meta = $wrapped->getMetadata();
     $config = $this->listener->getConfiguration($em, $meta->name);
     $closureMeta = $em->getClassMetadata($config['closure']);
     $nodeId = $wrapped->getIdentifier();
     $parent = $wrapped->getPropertyValue($config['parent']);
     $table = $closureMeta->getTableName();
     $conn = $em->getConnection();
     // ensure integrity
     if ($parent) {
         $dql = "SELECT COUNT(c) FROM {$closureMeta->name} c";
         $dql .= " WHERE c.ancestor = :node";
         $dql .= " AND c.descendant = :parent";
         $q = $em->createQuery($dql);
         $q->setParameters(compact('node', 'parent'));
         if ($q->getSingleScalarResult()) {
             throw new \Gedmo\Exception\UnexpectedValueException("Cannot set child as parent to node: {$nodeId}");
         }
     }
     if ($oldParent) {
         $subQuery = "SELECT c2.id FROM {$table} c1";
         $subQuery .= " JOIN {$table} c2 ON c1.descendant = c2.descendant";
         $subQuery .= " WHERE c1.ancestor = :nodeId AND c2.depth > c1.depth";
         $ids = $conn->fetchAll($subQuery, compact('nodeId'));
         if ($ids) {
             $ids = array_map(function ($el) {
                 return $el['id'];
             }, $ids);
         }
         // using subquery directly, sqlite acts unfriendly
         $query = "DELETE FROM {$table} WHERE id IN (" . implode(', ', $ids) . ")";
         if (!$conn->executeQuery($query)) {
             throw new RuntimeException('Failed to remove old closures');
         }
     }
     if ($parent) {
         $wrappedParent = AbstractWrapper::wrap($parent, $em);
         $parentId = $wrappedParent->getIdentifier();
         $query = "SELECT c1.ancestor, c2.descendant, (c1.depth + c2.depth + 1) AS depth";
         $query .= " FROM {$table} c1, {$table} c2";
         $query .= " WHERE c1.descendant = :parentId";
         $query .= " AND c2.ancestor = :nodeId";
         $closures = $conn->fetchAll($query, compact('nodeId', 'parentId'));
         foreach ($closures as $closure) {
             if (!$conn->insert($table, $closure)) {
                 throw new RuntimeException('Failed to insert new Closure record');
             }
         }
     }
     if (isset($config['level'])) {
         $this->pendingNodesLevelProcess[$nodeId] = $node;
     }
 }
Beispiel #4
0
 /**
  * Shift range of right and left values on tree
  * depending on tree level difference also
  *
  * @param EntityManager $em
  * @param string $class
  * @param integer $first
  * @param integer $last
  * @param integer $delta
  * @param integer|string $rootId
  * @param integer|string $destRootId
  * @param integer $levelDelta
  * @return void
  */
 public function shiftRangeRL(EntityManager $em, $class, $first, $last, $delta, $rootId = null, $destRootId = null, $levelDelta = null)
 {
     $meta = $em->getClassMetadata($class);
     $config = $this->listener->getConfiguration($em, $class);
     $sign = $delta >= 0 ? ' + ' : ' - ';
     $absDelta = abs($delta);
     $levelSign = $levelDelta >= 0 ? ' + ' : ' - ';
     $absLevelDelta = abs($levelDelta);
     $qb = $em->createQueryBuilder();
     $qb->update($config['useObjectClass'], 'node')->set('node.' . $config['left'], "node.{$config['left']} {$sign} {$absDelta}")->set('node.' . $config['right'], "node.{$config['right']} {$sign} {$absDelta}")->where($qb->expr()->gte('node.' . $config['left'], $first))->andWhere($qb->expr()->lte('node.' . $config['right'], $last));
     if (isset($config['root'])) {
         $qb->set('node.' . $config['root'], is_string($destRootId) ? $qb->expr()->literal($destRootId) : $destRootId);
         $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 (isset($config['level'])) {
         $qb->set('node.' . $config['level'], "node.{$config['level']} {$levelSign} {$absLevelDelta}");
     }
     $qb->getQuery()->getSingleScalarResult();
     // update in memory nodes increases performance, saves some IO
     foreach ($em->getUnitOfWork()->getIdentityMap() as $className => $nodes) {
         // for inheritance mapped classes, only root is always in the identity map
         if ($className !== $meta->rootEntityName) {
             continue;
         }
         foreach ($nodes as $node) {
             if ($node instanceof Proxy && !$node->__isInitialized__) {
                 continue;
             }
             $left = $meta->getReflectionProperty($config['left'])->getValue($node);
             $right = $meta->getReflectionProperty($config['right'])->getValue($node);
             $root = isset($config['root']) ? $meta->getReflectionProperty($config['root'])->getValue($node) : null;
             if ($root === $rootId && $left >= $first && $right <= $last) {
                 $oid = spl_object_hash($node);
                 $uow = $em->getUnitOfWork();
                 $meta->getReflectionProperty($config['left'])->setValue($node, $left + $delta);
                 $uow->setOriginalEntityProperty($oid, $config['left'], $left + $delta);
                 $meta->getReflectionProperty($config['right'])->setValue($node, $right + $delta);
                 $uow->setOriginalEntityProperty($oid, $config['right'], $right + $delta);
                 if (isset($config['root'])) {
                     $meta->getReflectionProperty($config['root'])->setValue($node, $destRootId);
                     $uow->setOriginalEntityProperty($oid, $config['root'], $destRootId);
                 }
                 if (isset($config['level'])) {
                     $level = $meta->getReflectionProperty($config['level'])->getValue($node);
                     $meta->getReflectionProperty($config['level'])->setValue($node, $level + $levelDelta);
                     $uow->setOriginalEntityProperty($oid, $config['level'], $level + $levelDelta);
                 }
             }
         }
     }
 }
 /**
  * Process pre-locking actions
  *
  * @param ObjectManager    $om
  * @param AdapterInterface $ea
  * @param object           $node
  * @param string           $action
  *
  * @return void
  */
 public function processPostEventsActions(ObjectManager $om, AdapterInterface $ea, $node, $action)
 {
     $meta = $om->getClassMetadata(get_class($node));
     $config = $this->listener->getConfiguration($om, $meta->name);
     if ($config['activate_locking']) {
         switch ($action) {
             case self::ACTION_INSERT:
                 unset($this->pendingObjectsToInsert[spl_object_hash($node)]);
                 break;
             case self::ACTION_UPDATE:
                 unset($this->pendingObjectsToUpdate[spl_object_hash($node)]);
                 break;
             case self::ACTION_REMOVE:
                 unset($this->pendingObjectsToRemove[spl_object_hash($node)]);
                 break;
             default:
                 throw new \InvalidArgumentException(sprintf('"%s" is not a valid action.', $action));
         }
         if (empty($this->pendingObjectsToInsert) && empty($this->pendingObjectsToUpdate) && empty($this->pendingObjectsToRemove)) {
             $this->releaseTreeLocks($om, $ea);
         }
     }
 }