public function testTreeMetadata()
 {
     $meta = $this->em->getClassMetadata('Mapping\\Fixture\\Xml\\ClosureTree');
     $config = $this->tree->getConfiguration($this->em, $meta->name);
     $this->assertArrayHasKey('strategy', $config);
     $this->assertEquals('closure', $config['strategy']);
     $this->assertArrayHasKey('closure', $config);
     $this->assertEquals('Mapping\\Fixture\\ClosureTreeClosure', $config['closure']);
     $this->assertArrayHasKey('parent', $config);
     $this->assertEquals('parent', $config['parent']);
 }
 /**
  * {@inheritDoc}
  */
 public function buildTreeArray(array $nodes)
 {
     $meta = $this->getClassMetadata();
     $config = $this->listener->getConfiguration($this->om, $meta->name);
     $nestedTree = array();
     $l = 0;
     if (count($nodes) > 0) {
         // Node Stack. Used to help building the hierarchy
         $stack = array();
         foreach ($nodes as $child) {
             $item = $child;
             $item[$this->childrenIndex] = array();
             // Number of stack items
             $l = count($stack);
             // Check if we're dealing with different levels
             while ($l > 0 && $stack[$l - 1][$config['level']] >= $item[$config['level']]) {
                 array_pop($stack);
                 $l--;
             }
             // Stack is empty (we are inspecting the root)
             if ($l == 0) {
                 // Assigning the root child
                 $i = count($nestedTree);
                 $nestedTree[$i] = $item;
                 $stack[] =& $nestedTree[$i];
             } else {
                 // Add child to parent
                 $i = count($stack[$l - 1][$this->childrenIndex]);
                 $stack[$l - 1][$this->childrenIndex][$i] = $item;
                 $stack[] =& $stack[$l - 1][$this->childrenIndex][$i];
             }
         }
     }
     return $nestedTree;
 }
 public function testTreeMetadata()
 {
     $meta = $this->em->getClassMetadata('Mapping\\Fixture\\Xml\\NestedTree');
     $config = $this->tree->getConfiguration($this->em, $meta->name);
     $this->assertArrayHasKey('strategy', $config);
     $this->assertEquals('nested', $config['strategy']);
     $this->assertArrayHasKey('left', $config);
     $this->assertEquals('left', $config['left']);
     $this->assertArrayHasKey('right', $config);
     $this->assertEquals('right', $config['right']);
     $this->assertArrayHasKey('level', $config);
     $this->assertEquals('level', $config['level']);
     $this->assertArrayHasKey('root', $config);
     $this->assertEquals('root', $config['root']);
     $this->assertArrayHasKey('parent', $config);
     $this->assertEquals('parent', $config['parent']);
 }
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 $root
  * @param integer|string $destRoot
  * @param integer        $levelDelta
  */
 public function shiftRangeRL(EntityManager $em, $class, $first, $last, $delta, $root = null, $destRoot = 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'], ':drid');
         $qb->setParameter('drid', $destRoot);
         $qb->andWhere($qb->expr()->eq('node.' . $config['root'], ':rid'));
         $qb->setParameter('rid', $root);
     }
     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;
             }
             $nodeMeta = $em->getClassMetadata(get_class($node));
             if (!array_key_exists($config['left'], $nodeMeta->getReflectionProperties())) {
                 continue;
             }
             $left = $meta->getReflectionProperty($config['left'])->getValue($node);
             $right = $meta->getReflectionProperty($config['right'])->getValue($node);
             $currentRoot = isset($config['root']) ? $meta->getReflectionProperty($config['root'])->getValue($node) : null;
             if ($currentRoot === $root && $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, $destRoot);
                     $uow->setOriginalEntityProperty($oid, $config['root'], $destRoot);
                 }
                 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);
                 }
             }
         }
     }
 }
 function let(UserContext $userContext, EntityManager $em, ClassMetadata $classMetadata, EventManager $eventManager, TreeListener $treeListener, Nested $strategy)
 {
     $classMetadata->name = 'category';
     $userContext->getCurrentLocaleCode()->willReturn('en_US');
     $em->getEventManager()->willReturn($eventManager);
     $eventManager->getListeners()->willReturn([[$treeListener]]);
     $treeListener->getStrategy(Argument::cetera())->willReturn($strategy);
     $treeListener->getConfiguration(Argument::cetera())->willReturn(['parent' => 'parent', 'left' => 'left']);
     $this->beConstructedWith($userContext, $em, $classMetadata);
 }
Beispiel #6
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;
     }
 }
 public function testTreeMetadata()
 {
     $meta = $this->em->getClassMetadata('Mapping\\Fixture\\Xml\\MaterializedPathTree');
     $config = $this->tree->getConfiguration($this->em, $meta->name);
     $this->assertArrayHasKey('strategy', $config);
     $this->assertEquals('materializedPath', $config['strategy']);
     $this->assertArrayHasKey('activate_locking', $config);
     $this->assertTrue($config['activate_locking']);
     $this->assertArrayHasKey('locking_timeout', $config);
     $this->assertEquals(10, $config['locking_timeout']);
     $this->assertArrayHasKey('level', $config);
     $this->assertEquals('level', $config['level']);
     $this->assertArrayHasKey('parent', $config);
     $this->assertEquals('parent', $config['parent']);
     $this->assertArrayHasKey('path_source', $config);
     $this->assertEquals('title', $config['path_source']);
     $this->assertArrayHasKey('path', $config);
     $this->assertEquals('path', $config['path']);
     $this->assertArrayHasKey('lock_time', $config);
     $this->assertEquals('lockTime', $config['lock_time']);
 }
 function let(EntityManager $em, Connection $connection, Statement $statement, ClassMetadata $classMetadata, EventManager $eventManager, TreeListener $treeListener, Nested $strategy, \ReflectionProperty $property)
 {
     $connection->prepare(Argument::any())->willReturn($statement);
     $em->getClassMetadata(Argument::any())->willReturn($classMetadata);
     $classMetadata->name = 'channel';
     $classMetadata->getReflectionProperty(Argument::any())->willReturn($property);
     $em->getConnection()->willReturn($connection);
     $em->getEventManager()->willReturn($eventManager);
     $em->getClassMetadata()->willReturn($classMetadata);
     $strategy->getName()->willReturn(Strategy::NESTED);
     $strategy->setNodePosition(Argument::cetera())->willReturn(null);
     $treeListener->getStrategy(Argument::cetera())->willReturn($strategy);
     $configuration = ['parent' => 'parent', 'left' => 'left'];
     $treeListener->getConfiguration(Argument::cetera())->willReturn($configuration);
     $eventManager->getListeners()->willReturn([[$treeListener]]);
     $this->beConstructedWith($em, $classMetadata);
 }
 public function testYamlMaterializedPathMapping()
 {
     $meta = $this->em->getClassMetadata(self::YAML_MATERIALIZED_PATH_CATEGORY);
     $config = $this->listener->getConfiguration($this->em, $meta->name);
     $this->assertArrayHasKey('strategy', $config);
     $this->assertEquals('materializedPath', $config['strategy']);
     $this->assertArrayHasKey('parent', $config);
     $this->assertEquals('parent', $config['parent']);
     $this->assertArrayHasKey('activate_locking', $config);
     $this->assertTrue($config['activate_locking']);
     $this->assertArrayHasKey('locking_timeout', $config);
     $this->assertEquals(3, $config['locking_timeout']);
     $this->assertArrayHasKey('level', $config);
     $this->assertEquals('level', $config['level']);
     $this->assertArrayHasKey('path', $config);
     $this->assertEquals('path', $config['path']);
     $this->assertArrayHasKey('path_separator', $config);
     $this->assertEquals(',', $config['path_separator']);
 }
 /**
  * {@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;
 }
Beispiel #11
0
 public function testYamlMaterializedPathMapping()
 {
     if (!extension_loaded('apc') || !ini_get('apc.enable_cli')) {
         $this->markTestSkipped('APC extension is not loaded.');
     }
     $meta = $this->em->getClassMetadata(self::YAML_MATERIALIZED_PATH_CATEGORY);
     $config = $this->listener->getConfiguration($this->em, $meta->name);
     $this->assertArrayHasKey('strategy', $config);
     $this->assertEquals('materializedPath', $config['strategy']);
     $this->assertArrayHasKey('parent', $config);
     $this->assertEquals('parent', $config['parent']);
     $this->assertArrayHasKey('activate_locking', $config);
     $this->assertTrue($config['activate_locking']);
     $this->assertArrayHasKey('locking_timeout', $config);
     $this->assertEquals(3, $config['locking_timeout']);
     $this->assertArrayHasKey('level', $config);
     $this->assertEquals('level', $config['level']);
     $this->assertArrayHasKey('path', $config);
     $this->assertEquals('path', $config['path']);
     $this->assertArrayHasKey('path_separator', $config);
     $this->assertEquals(',', $config['path_separator']);
 }