Cache the trees structures for treeViews used in the sidebar.

This commit is contained in:
Jan Böhmer 2020-01-02 18:45:41 +01:00
parent 9668d1084b
commit ad69c32832
13 changed files with 653 additions and 70 deletions

View file

@ -27,114 +27,94 @@ use App\Entity\Parts\Footprint;
use App\Entity\Parts\Manufacturer;
use App\Entity\Parts\Storelocation;
use App\Entity\Parts\Supplier;
use App\Entity\UserSystem\U2FKey;
use App\Entity\UserSystem\User;
use App\Services\ToolsTreeBuilder;
use App\Services\TreeBuilder;
use App\Services\Trees\TreeViewGenerator;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
/**
* This controller has the purpose to provide the data for all treeviews.
* @Route("/tree")
*/
class TreeController extends AbstractController
{
protected $treeGenerator;
public function __construct(TreeViewGenerator $treeGenerator)
{
$this->treeGenerator = $treeGenerator;
}
/**
* @Route("/tree/tools", name="tree_tools")
* @Route("/tools", name="tree_tools")
*/
public function tools(ToolsTreeBuilder $builder)
{
$tree = $builder->getTree();
//Ignore null values, to save data
return $this->json($tree, 200, [], ['skip_null_values' => true]);
}
/**
* @Route("/tree/category/{id}", name="tree_category")
* @Route("/tree/categories")
* @Route("/category/{id}", name="tree_category")
* @Route("/categories")
*/
public function categoryTree(TreeBuilder $builder, Category $category = null)
public function categoryTree(Category $category = null)
{
if (null !== $category) {
$tree[] = $builder->elementToTreeNode($category);
} else {
$tree = $builder->typeToTree(Category::class);
}
$tree = $this->treeGenerator->getTreeView(Category::class, $category);
return $this->json($tree, 200, [], ['skip_null_values' => true]);
}
/**
* @Route("/tree/footprint/{id}", name="tree_footprint")
* @Route("/tree/footprints")
* @Route("/footprint/{id}", name="tree_footprint")
* @Route("/footprints")
*/
public function footprintTree(TreeBuilder $builder, Footprint $footprint = null)
public function footprintTree(Footprint $footprint = null)
{
if (null !== $footprint) {
$tree[] = $builder->elementToTreeNode($footprint);
} else {
$tree = $builder->typeToTree(Footprint::class);
}
$tree = $this->treeGenerator->getTreeView(Footprint::class, $footprint);
return $this->json($tree, 200, [], ['skip_null_values' => true]);
}
/**
* @Route("/tree/location/{id}", name="tree_location")
* @Route("/tree/locations")
* @Route("/location/{id}", name="tree_location")
* @Route("/locations")
*/
public function locationTree(TreeBuilder $builder, Storelocation $location = null)
public function locationTree(Storelocation $location = null)
{
if (null !== $location) {
$tree[] = $builder->elementToTreeNode($location);
} else {
$tree = $builder->typeToTree(Storelocation::class);
}
$tree = $this->treeGenerator->getTreeView(Storelocation::class, $location);
return $this->json($tree, 200, [], ['skip_null_values' => true]);
}
/**
* @Route("/tree/manufacturer/{id}", name="tree_manufacturer")
* @Route("/tree/manufacturers")
* @Route("/manufacturer/{id}", name="tree_manufacturer")
* @Route("/manufacturers")
*/
public function manufacturerTree(TreeBuilder $builder, Manufacturer $manufacturer = null)
public function manufacturerTree(Manufacturer $manufacturer = null)
{
if (null !== $manufacturer) {
$tree[] = $builder->elementToTreeNode($manufacturer);
} else {
$tree = $builder->typeToTree(Manufacturer::class);
}
$tree = $this->treeGenerator->getTreeView(Manufacturer::class, $manufacturer);
return $this->json($tree, 200, [], ['skip_null_values' => true]);
}
/**
* @Route("/tree/supplier/{id}", name="tree_supplier")
* @Route("/tree/suppliers")
* @Route("/supplier/{id}", name="tree_supplier")
* @Route("/suppliers")
*/
public function supplierTree(TreeBuilder $builder, Supplier $supplier = null)
public function supplierTree(Supplier $supplier = null)
{
if (null !== $supplier) {
$tree[] = $builder->elementToTreeNode($supplier);
} else {
$tree = $builder->typeToTree(Supplier::class);
}
$tree = $this->treeGenerator->getTreeView(Supplier::class, $supplier);
return $this->json($tree, 200, [], ['skip_null_values' => true]);
}
/**
* @Route("/tree/device/{id}", name="tree_device")
* @Route("/tree/devices")
* @Route("/device/{id}", name="tree_device")
* @Route("/devices")
*/
public function deviceTree(TreeBuilder $builder, Device $device = null)
public function deviceTree(Device $device = null)
{
if (null !== $device) {
$tree[] = $builder->elementToTreeNode($device);
} else {
$tree = $builder->typeToTree(Device::class, null);
}
$tree = $this->treeGenerator->getTreeView(Device::class, $device, '');
return $this->json($tree, 200, [], ['skip_null_values' => true]);
}
}

View file

@ -30,7 +30,7 @@ use Symfony\Component\Validator\Constraints as Assert;
/**
* All subclasses of this class have an attribute "name".
*
* @ORM\MappedSuperclass()
* @ORM\MappedSuperclass(repositoryClass="App\Repository\UserRepository")
* @ORM\HasLifecycleCallbacks()
*/
abstract class NamedDBElement extends DBElement

View file

@ -26,6 +26,7 @@ namespace App\Entity\Base;
use App\Entity\Attachments\AttachmentContainingDBElement;
use App\Validator\Constraints\NoneOfItsChildren;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Serializer\Annotation\Groups;
@ -244,13 +245,16 @@ abstract class StructuralDBElement extends AttachmentContainingDBElement
*
* @param bool $recursive if true, the search is recursive
*
* @return static[] all subelements as an array of objects (sorted by their full path)
* @return Collection<static> all subelements as an array of objects (sorted by their full path)
*/
public function getSubelements(): iterable
{
return $this->children;
}
/**
* @return Collection<static>
*/
public function getChildren(): iterable
{
return $this->children;

View file

@ -21,6 +21,10 @@
namespace App\Helpers;
use App\Entity\Base\DBElement;
use App\Entity\Base\NamedDBElement;
use App\Entity\Base\StructuralDBElement;
/**
* This class represents a node for the bootstrap treeview node.
* When you serialize an array of these objects to JSON, you can use the serialized data in data for the treeview.
@ -35,6 +39,8 @@ class TreeViewNode
protected $tags;
protected $id;
/**
* Creates a new TreeView node with the given parameters.
*
@ -53,6 +59,28 @@ class TreeViewNode
//$this->state = new TreeViewNodeState();
}
/**
* Return the ID of the entity associated with this node.
* Null if this node is not connected with an entity.
* @return int|null
*/
public function getId() : ?int
{
return $this->id;
}
/**
* Sets the ID of the entity associated with this node.
* Null if this node is not connected with an entity.
* @param int|null $id
* @return $this
*/
public function setId(?int $id): self
{
$this->id = $id;
return $this;
}
/**
* Returns the node text.
*
@ -104,7 +132,7 @@ class TreeViewNode
/**
* Returns the children nodes of this node.
*
* @return array|null
* @return TreeViewNode[]|null
*/
public function getNodes(): ?array
{

View file

@ -0,0 +1,58 @@
<?php
/**
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 Jan Böhmer (https://github.com/jbtronics)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
namespace App\Helpers\Trees;
use App\Entity\Base\StructuralDBElement;
use Doctrine\Common\Collections\Collection;
use RecursiveIterator;
class StructuralDBElementIterator extends \ArrayIterator implements \RecursiveIterator
{
/**
* @param $nodes Collection<StructuralDBElement>|StructuralDBElement[]
*/
public function __construct($nodes)
{
parent::__construct($nodes);
}
/**
* @inheritDoc
*/
public function hasChildren()
{
/** @var StructuralDBElement $element */
$element = $this->current();
return !empty($element->getSubelements());
}
/**
* @inheritDoc
*/
public function getChildren()
{
/** @var StructuralDBElement $element */
$element = $this->current();
return new StructuralDBElementIterator($element->getSubelements()->toArray());
}
}

View file

@ -0,0 +1,56 @@
<?php
/**
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 Jan Böhmer (https://github.com/jbtronics)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
namespace App\Helpers\Trees;
use App\Helpers\TreeViewNode;
class TreeViewNodeIterator extends \ArrayIterator implements \RecursiveIterator
{
/**
* @param $nodes TreeViewNode[]
*/
public function __construct($nodes)
{
parent::__construct($nodes);
}
/**
* @inheritDoc
*/
public function hasChildren()
{
/** @var TreeViewNode $element */
$element = $this->current();
return !empty($element->getNodes());
}
/**
* @inheritDoc
*/
public function getChildren()
{
/** @var TreeViewNode $element */
$element = $this->current();
return new TreeViewNodeIterator($element->getNodes());
}
}

View file

@ -0,0 +1,53 @@
<?php
/**
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 Jan Böhmer (https://github.com/jbtronics)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
namespace App\Repository;
use App\Entity\Base\NamedDBElement;
use App\Entity\Base\StructuralDBElement;
use App\Helpers\TreeViewNode;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Mapping\Entity;
class NamedDBElementRepository extends EntityRepository
{
/**
* Gets a tree of TreeViewNode elements. The root elements has $parent as parent.
* The treeview is generic, that means the href are null and ID values are set.
* @return TreeViewNode[]
*/
public function getGenericNodeTree() : array
{
$result = [];
$entities = $this->findAll();
foreach ($entities as $entity) {
/** @var $entity NamedDBElement */
$node = new TreeViewNode($entity->getName(), null, null);
$node->setId($entity->getID());
$result[] = $node;
}
return $result;
}
}

View file

@ -22,9 +22,12 @@
namespace App\Repository;
use App\Entity\Base\StructuralDBElement;
use App\Helpers\Trees\StructuralDBElementIterator;
use App\Helpers\TreeViewNode;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\Stopwatch\Stopwatch;
class StructuralDBElementRepository extends EntityRepository
class StructuralDBElementRepository extends NamedDBElementRepository
{
/**
* Finds all nodes without a parent node. They are our root nodes.
@ -36,6 +39,31 @@ class StructuralDBElementRepository extends EntityRepository
return $this->findBy(['parent' => null], ['name' => 'ASC']);
}
/**
* Gets a tree of TreeViewNode elements. The root elements has $parent as parent.
* The treeview is generic, that means the href are null and ID values are set.
* @param StructuralDBElement|null $parent The parent the root elements should have.
* @return TreeViewNode[]
*/
public function getGenericNodeTree(?StructuralDBElement $parent = null) : array
{
$result = [];
$entities = $this->findBy(['parent' => $parent], ['name' => 'ASC']);
foreach ($entities as $entity) {
/** @var StructuralDBElement $entity */
//Make a recursive call to find all children nodes
$children = $this->getGenericNodeTree($entity);
$node = new TreeViewNode($entity->getName(), null, $children);
//Set the ID of this entity to later be able to reconstruct the URL
$node->setId($entity->getID());
$result[] = $node;
}
return $result;
}
/**
* Gets a flattened hierarchical tree. Useful for generating option lists.
*
@ -49,16 +77,13 @@ class StructuralDBElementRepository extends EntityRepository
$entities = $this->findBy(['parent' => $parent], ['name' => 'ASC']);
/*
* I think it is very difficult to replace this recursive array_merge,
* so if you want to change it you should have a better idea than adding each list to $result array
* and do an array_merge(...$result) at the end.
*/
$elementIterator = new StructuralDBElementIterator($entities);
$recursiveIterator = new \RecursiveIteratorIterator($elementIterator, \RecursiveIteratorIterator::SELF_FIRST);
//$result = iterator_to_array($recursiveIterator);
foreach ($entities as $entity) {
/* @var StructuralDBElement $entity */
$result[] = $entity;
$result = array_merge($result, $this->toNodesList($entity));
//We can not use iterator_to_array here or we get only the parent elements
foreach($recursiveIterator as $item) {
$result[] = $item;
}
return $result;

View file

@ -37,7 +37,7 @@ use Symfony\Component\Security\Core\User\UserInterface;
* @method User[] findAll()
* @method User[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class UserRepository extends EntityRepository implements PasswordUpgraderInterface
class UserRepository extends NamedDBElementRepository implements PasswordUpgraderInterface
{
protected $anonymous_user;

View file

@ -0,0 +1,114 @@
<?php
/**
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 Jan Böhmer (https://github.com/jbtronics)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
namespace App\Services\Trees;
use App\Entity\Base\DBElement;
use App\Entity\Base\StructuralDBElement;
use App\Helpers\Trees\TreeViewNodeIterator;
use App\Helpers\TreeViewNode;
use App\Repository\StructuralDBElementRepository;
use App\Services\EntityURLGenerator;
use App\Services\UserCacheKeyGenerator;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Contracts\Cache\ItemInterface;
use Symfony\Contracts\Cache\TagAwareCacheInterface;
class TreeViewGenerator
{
protected $urlGenerator;
protected $em;
protected $cache;
protected $keyGenerator;
public function __construct(EntityURLGenerator $URLGenerator, EntityManagerInterface $em,
TagAwareCacheInterface $treeCache, UserCacheKeyGenerator $keyGenerator)
{
$this->urlGenerator = $URLGenerator;
$this->em = $em;
$this->cache = $treeCache;
$this->keyGenerator = $keyGenerator;
}
public function getTreeView(string $class, ?StructuralDBElement $parent = null, string $href_type = 'list_parts', DBElement $selectedElement = null)
{
$generic = $this->getGenericTree($class, $parent);
$treeIterator = new TreeViewNodeIterator($generic);
$recursiveIterator = new \RecursiveIteratorIterator($treeIterator);
foreach ($recursiveIterator as $item) {
/** @var $item TreeViewNode */
if ($selectedElement !== null && $item->getId() === $selectedElement->getID()) {
$item->setSelected(true);
}
if (!empty($item->getNodes())) {
$item->addTag((string) \count($item->getNodes()));
}
if (!empty($href_type)) {
$entity = $this->em->getPartialReference($class, $item->getId());
$item->setHref($this->urlGenerator->getURL($entity, $href_type));
}
}
return $generic;
}
/**
* /**
* Gets a tree of TreeViewNode elements. The root elements has $parent as parent.
* The treeview is generic, that means the href are null and ID values are set.
*
* @param string $class The class for which the tree should be generated
* @param StructuralDBElement|null $parent The parent the root elements should have.
* @return TreeViewNode[]
*/
public function getGenericTree(string $class, ?StructuralDBElement $parent = null) : array
{
if(!is_a($class, StructuralDBElement::class, true)) {
throw new \InvalidArgumentException('$class must be a class string that implements StructuralDBElement!');
}
if($parent !== null && !is_a($parent, $class)) {
throw new \InvalidArgumentException('$parent must be of the type class!');
}
/** @var StructuralDBElementRepository $repo */
$repo = $this->em->getRepository($class);
//If we just want a part of a tree, dont cache it
if ($parent !== null) {
return $repo->getGenericNodeTree($parent);
}
$secure_class_name = str_replace('\\', '_', $class);
$key = 'treeview_'.$this->keyGenerator->generateKey().'_'.$secure_class_name;
$ret = $this->cache->get($key, function (ItemInterface $item) use ($repo, $parent, $secure_class_name) {
// Invalidate when groups, a element with the class or the user changes
$item->tag(['groups', 'tree_treeview', $this->keyGenerator->generateKey(), $secure_class_name]);
return $repo->getGenericNodeTree($parent);
});
return $ret;
}
}

View file

@ -0,0 +1,66 @@
<?php
/**
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 Jan Böhmer (https://github.com/jbtronics)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
namespace App\Tests\Repository;
use App\Entity\Attachments\AttachmentType;
use App\Entity\UserSystem\User;
use App\Helpers\TreeViewNode;
use App\Repository\NamedDBElementRepository;
use App\Repository\StructuralDBElementRepository;
use PHPUnit\Framework\TestCase;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
/**
* @Group DB
*/
class NamedDBElementRepositoryTest extends WebTestCase
{
private $entityManager;
/** @var StructuralDBElementRepository */
private $repo;
/**
* {@inheritDoc}
*/
protected function setUp() : void
{
$kernel = self::bootKernel();
$this->entityManager = $kernel->getContainer()
->get('doctrine')
->getManager();
$this->repo = $this->entityManager->getRepository(User::class);
}
public function testGetGenericNodeTree()
{
$tree = $this->repo->getGenericNodeTree();
$this->assertIsArray($tree);
$this->assertContainsOnlyInstancesOf(TreeViewNode::class, $tree);
$this->assertCount(4, $tree);
$this->assertEquals('anonymous', $tree[0]->getText());
$this->assertEmpty($tree[0]->getNodes());
}
}

View file

@ -0,0 +1,123 @@
<?php
/**
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 Jan Böhmer (https://github.com/jbtronics)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
namespace App\Tests\Repository;
use App\Entity\Attachments\AttachmentType;
use App\Helpers\TreeViewNode;
use App\Repository\StructuralDBElementRepository;
use PHPUnit\Framework\TestCase;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
/**
* @Group DB
*/
class StructuralDBElementRepositoryTest extends WebTestCase
{
private $entityManager;
/** @var StructuralDBElementRepository */
private $repo;
/**
* {@inheritDoc}
*/
protected function setUp() : void
{
$kernel = self::bootKernel();
$this->entityManager = $kernel->getContainer()
->get('doctrine')
->getManager();
$this->repo = $this->entityManager->getRepository(AttachmentType::class);
}
public function testFindRootNodes() : void
{
$root_nodes = $this->repo->findRootNodes();
$this->assertCount(3, $root_nodes);
$this->assertContainsOnlyInstancesOf(AttachmentType::class, $root_nodes);
//Asc sorting
$this->assertEquals('Node 1', $root_nodes[0]->getName());
$this->assertEquals('Node 2', $root_nodes[1]->getName());
$this->assertEquals('Node 3', $root_nodes[2]->getName());
}
public function testGetGenericTree() : void
{
$tree = $this->repo->getGenericNodeTree();
$this->assertIsArray($tree);
$this->assertContainsOnlyInstancesOf(TreeViewNode::class, $tree);
$this->assertCount(3, $tree);
$this->assertCount(2, $tree[0]->getNodes());
$this->assertCount(1, $tree[0]->getNodes()[0]->getNodes());
$this->assertEmpty($tree[2]->getNodes());
$this->assertEmpty($tree[1]->getNodes()[0]->getNodes());
//Check text
$this->assertEquals('Node 1', $tree[0]->getText());
$this->assertEquals('Node 2', $tree[1]->getText());
$this->assertEquals('Node 3', $tree[2]->getText());
$this->assertEquals('Node 1.1', $tree[0]->getNodes()[0]->getText());
$this->assertEquals('Node 1.1.1', $tree[0]->getNodes()[0]->getNodes()[0]->getText());
//Check that IDs were set correctly
$this->assertEquals(1, $tree[0]->getId());
$this->assertEquals(2, $tree[1]->getId());
$this->assertEquals(7, $tree[0]->getNodes()[0]->getNodes()[0]->getId());
}
/**
* Test $repo->toNodesList() for null as parameter
*/
public function testToNodesListRoot() : void
{
//List all root nodes and their children
$nodes = $this->repo->toNodesList();
$this->assertCount(7, $nodes);
$this->assertContainsOnlyInstancesOf(AttachmentType::class, $nodes);
$this->assertEquals('Node 1', $nodes[0]->getName());
$this->assertEquals('Node 1.1', $nodes[1]->getName());
$this->assertEquals('Node 1.1.1', $nodes[2]->getName());
$this->assertEquals('Node 1.2', $nodes[3]->getName());
$this->assertEquals('Node 2', $nodes[4]->getName());
$this->assertEquals('Node 2.1', $nodes[5]->getName());
$this->assertEquals('Node 3', $nodes[6]->getName());
}
public function testToNodesListElement() : void
{
//List all nodes that are children to Node 1
$node1 = $this->repo->find(1);
$nodes = $this->repo->toNodesList($node1);
$this->assertCount(3, $nodes);
$this->assertContainsOnlyInstancesOf(AttachmentType::class, $nodes);
$this->assertEquals('Node 1.1', $nodes[0]->getName());
$this->assertEquals('Node 1.1.1', $nodes[1]->getName());
$this->assertEquals('Node 1.2', $nodes[2]->getName());
}
}

View file

@ -0,0 +1,76 @@
<?php
/**
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 Jan Böhmer (https://github.com/jbtronics)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
namespace App\Tests\Services\Trees;
use App\Entity\Attachments\AttachmentType;
use App\Helpers\TreeViewNode;
use App\Services\AmountFormatter;
use App\Services\Trees\TreeViewGenerator;
use PHPUnit\Framework\TestCase;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
/**
* @group DB
*/
class TreeGeneratorTest extends WebTestCase
{
/**
* @var TreeViewGenerator
*/
protected $service;
public function setUp() : void
{
parent::setUp(); // TODO: Change the autogenerated stub
//Get an service instance.
self::bootKernel();
$this->service = self::$container->get(TreeViewGenerator::class);
}
public function testGetGenericTree()
{
$tree = $this->service->getGenericTree(AttachmentType::class, null);
$this->assertIsArray($tree);
$this->assertContainsOnlyInstancesOf(TreeViewNode::class, $tree);
$this->assertCount(3, $tree);
$this->assertCount(2, $tree[0]->getNodes());
$this->assertCount(1, $tree[0]->getNodes()[0]->getNodes());
$this->assertEmpty($tree[2]->getNodes());
$this->assertEmpty($tree[1]->getNodes()[0]->getNodes());
//Check text
$this->assertEquals('Node 1', $tree[0]->getText());
$this->assertEquals('Node 2', $tree[1]->getText());
$this->assertEquals('Node 3', $tree[2]->getText());
$this->assertEquals('Node 1.1', $tree[0]->getNodes()[0]->getText());
$this->assertEquals('Node 1.1.1', $tree[0]->getNodes()[0]->getNodes()[0]->getText());
//Check that IDs were set correctly
$this->assertEquals(1, $tree[0]->getId());
$this->assertEquals(2, $tree[1]->getId());
$this->assertEquals(7, $tree[0]->getNodes()[0]->getNodes()[0]->getId());
}
}