Use new cached treeview nodes for twig inline generator (admin pages)

This commit is contained in:
Jan Böhmer 2020-01-02 22:55:28 +01:00
parent ad69c32832
commit d9b15ddbb9
20 changed files with 277 additions and 214 deletions

View file

@ -3,6 +3,8 @@ controllers:
type: annotation
prefix: '{_locale}'
defaults:
_locale: '%kernel.default_locale%'
requirements:
# Match only locales like de_DE or de
_locale: "^[a-z]{2}(_[A-Z]{2})?$"

View file

@ -29,8 +29,8 @@ 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\ToolsTreeBuilder;
use App\Services\Trees\NodesListBuilder;
use App\Services\Trees\TreeViewGenerator;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;

View file

@ -40,7 +40,7 @@ use App\Services\Attachments\PartPreviewGenerator;
use App\Services\EntityURLGenerator;
use App\Services\FAIconGenerator;
use App\Services\MarkdownParser;
use App\Services\TreeBuilder;
use App\Services\Trees\NodesListBuilder;
use Doctrine\ORM\QueryBuilder;
use Omines\DataTablesBundle\Adapter\Doctrine\ORM\SearchCriteriaProvider;
use Omines\DataTablesBundle\Adapter\Doctrine\ORMAdapter;
@ -65,7 +65,7 @@ class PartsDataTable implements DataTableTypeInterface
protected $attachmentURLGenerator;
public function __construct(EntityURLGenerator $urlGenerator, TranslatorInterface $translator,
TreeBuilder $treeBuilder, AmountFormatter $amountFormatter,
NodesListBuilder $treeBuilder, AmountFormatter $amountFormatter,
PartPreviewGenerator $previewGenerator, AttachmentURLGenerator $attachmentURLGenerator)
{
$this->urlGenerator = $urlGenerator;

View file

@ -23,7 +23,7 @@ namespace App\Form\Type;
use App\Entity\Base\StructuralDBElement;
use App\Entity\PriceInformations\Currency;
use App\Services\TreeBuilder;
use App\Services\Trees\NodesListBuilder;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Intl\Currencies;
use Symfony\Component\OptionsResolver\Options;
@ -33,7 +33,7 @@ class CurrencyEntityType extends StructuralEntityType
{
protected $base_currency;
public function __construct(EntityManagerInterface $em, TreeBuilder $builder, $base_currency)
public function __construct(EntityManagerInterface $em, NodesListBuilder $builder, $base_currency)
{
parent::__construct($em, $builder);
$this->base_currency = $base_currency;

View file

@ -24,7 +24,7 @@ namespace App\Form\Type;
use App\Entity\Attachments\AttachmentType;
use App\Entity\Base\StructuralDBElement;
use App\Repository\StructuralDBElementRepository;
use App\Services\TreeBuilder;
use App\Services\Trees\NodesListBuilder;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\CallbackTransformer;
@ -47,10 +47,10 @@ class StructuralEntityType extends AbstractType
{
protected $em;
protected $options;
/** @var TreeBuilder */
/** @var NodesListBuilder */
protected $builder;
public function __construct(EntityManagerInterface $em, TreeBuilder $builder)
public function __construct(EntityManagerInterface $em, NodesListBuilder $builder)
{
$this->em = $em;
$this->builder = $builder;

View file

@ -19,11 +19,12 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
namespace App\Helpers;
namespace App\Helpers\Trees;
use App\Entity\Base\DBElement;
use App\Entity\Base\NamedDBElement;
use App\Entity\Base\StructuralDBElement;
use App\Helpers\Trees\TreeViewNodeState;
/**
* This class represents a node for the bootstrap treeview node.

View file

@ -21,7 +21,7 @@
namespace App\Helpers\Trees;
use App\Helpers\TreeViewNode;
use App\Helpers\Trees\TreeViewNode;
class TreeViewNodeIterator extends \ArrayIterator implements \RecursiveIterator
{

View file

@ -19,7 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
namespace App\Helpers;
namespace App\Helpers\Trees;
class TreeViewNodeState
{

View file

@ -24,7 +24,7 @@ namespace App\Repository;
use App\Entity\Base\NamedDBElement;
use App\Entity\Base\StructuralDBElement;
use App\Helpers\TreeViewNode;
use App\Helpers\Trees\TreeViewNode;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Mapping\Entity;

View file

@ -23,7 +23,7 @@ namespace App\Repository;
use App\Entity\Base\StructuralDBElement;
use App\Helpers\Trees\StructuralDBElementIterator;
use App\Helpers\TreeViewNode;
use App\Helpers\Trees\TreeViewNode;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\Stopwatch\Stopwatch;

View file

@ -1,182 +0,0 @@
<?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;
use App\Entity\Base\DBElement;
use App\Entity\Base\NamedDBElement;
use App\Entity\Base\StructuralDBElement;
use App\Helpers\TreeViewNode;
use App\Repository\StructuralDBElementRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Contracts\Cache\ItemInterface;
use Symfony\Contracts\Cache\TagAwareCacheInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
/**
* This service gives you multiple possibilities to generate trees.
*/
class TreeBuilder
{
protected $url_generator;
protected $em;
protected $translator;
protected $cache;
protected $keyGenerator;
public function __construct(EntityURLGenerator $URLGenerator, EntityManagerInterface $em,
TranslatorInterface $translator, TagAwareCacheInterface $treeCache, UserCacheKeyGenerator $keyGenerator)
{
$this->url_generator = $URLGenerator;
$this->em = $em;
$this->translator = $translator;
$this->keyGenerator = $keyGenerator;
$this->cache = $treeCache;
}
/**
* Generates a tree for the given Element. The given element is the top node, all children are child nodes.
*
* @param StructuralDBElement $element The element for which the tree should be generated.
* @param string $href_type The type of the links that should be used for the links. Set to null, to disable links.
* See EntityURLGenerator::getURL for possible types.
* @param DBElement|null $selectedElement When a element is given here, its tree node will be marked as selected in
* the resulting tree. When $selectedElement is not existing in the tree, then nothing happens.
*
* @return TreeViewNode The Node for the given Element.
*
* @throws \App\Exceptions\EntityNotSupportedException
*/
public function elementToTreeNode(NamedDBElement $element, ?string $href_type = 'list_parts', DBElement $selectedElement = null): TreeViewNode
{
$children_nodes = null;
if ($element instanceof StructuralDBElement) {
$children = $element->getSubelements();
foreach ($children as $child) {
$children_nodes[] = $this->elementToTreeNode($child, $href_type, $selectedElement);
}
}
//Check if we need to generate a href type
$href = null;
if (!empty($href_type)) {
$href = $this->url_generator->getURL($element, $href_type);
}
$tree_node = new TreeViewNode($element->__toString(), $href, $children_nodes);
if (null != $children_nodes) {
$tree_node->addTag((string) \count($children_nodes));
}
//Check if we need to select the current part
if (null !== $selectedElement && $element->getID() === $selectedElement->getID()) {
$tree_node->setSelected(true);
}
return $tree_node;
}
/**
* Generates a tree for all elements of the given type.
*
* @param StructuralDBElement $class_name The class name of the StructuralDBElement class for which the tree should
* be generated.
* @param string $href_type The type of the links that should be used for the links. Set to null, to disable links.
* See EntityURLGenerator::getURL for possible types.
* @param DBElement|null $selectedElement When a element is given here, its tree node will be marked as selected in
* the resulting tree. When $selectedElement is not existing in the tree, then nothing happens.
*
* @return TreeViewNode[] Returns an array, containing all nodes. It is empty if the given class has no elements.
*
* @throws \App\Exceptions\EntityNotSupportedException
*/
public function typeToTree(string $class_name, ?string $href_type = 'list_parts', DBElement $selectedElement = null): array
{
/**
* @var StructuralDBElementRepository
*/
$repo = $this->em->getRepository($class_name);
if (new $class_name() instanceof StructuralDBElement) {
$root_nodes = $repo->findRootNodes();
} else {
$root_nodes = $repo->findAll();
}
$array = [];
//When we use the newEdit type, add the New Element node.
if ('newEdit' === $href_type) {
//Generate the url for the new node
$href = $this->url_generator->createURL(new $class_name());
$new_node = new TreeViewNode($this->translator->trans('entity.tree.new'), $href);
//When the id of the selected element is null, then we have a new element, and we need to select "new" node
if (null != $selectedElement && null == $selectedElement->getID()) {
$new_node->setSelected(true);
}
$array[] = $new_node;
//Add spacing
$array[] = (new TreeViewNode(''))->setDisabled(true);
//Every other treeNode will be used for edit
$href_type = 'edit';
}
foreach ($root_nodes as $node) {
$array[] = $this->elementToTreeNode($node, $href_type, $selectedElement);
}
return $array;
}
/**
* Gets a flattened hierachical tree. Useful for generating option lists.
* In difference to the Repository Function, the results here are cached.
*
* @param string $class_name The class name of the entity you want to retrieve.
* @param StructuralDBElement|null $parent This entity will be used as root element. Set to null, to use global root
*
* @return StructuralDBElement[] A flattened list containing the tree elements.
*/
public function typeToNodesList(string $class_name, ?StructuralDBElement $parent = null): array
{
$parent_id = null != $parent ? $parent->getID() : '0';
// Backslashes are not allowed in cache keys
$secure_class_name = str_replace('\\', '_', $class_name);
$key = 'list_'.$this->keyGenerator->generateKey().'_'.$secure_class_name.$parent_id;
$ret = $this->cache->get($key, function (ItemInterface $item) use ($class_name, $parent, $secure_class_name) {
// Invalidate when groups, a element with the class or the user changes
$item->tag(['groups', 'tree_list', $this->keyGenerator->generateKey(), $secure_class_name]);
/**
* @var StructuralDBElementRepository
*/
$repo = $this->em->getRepository($class_name);
return $repo->toNodesList($parent);
});
return $ret;
}
}

View file

@ -0,0 +1,81 @@
<?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\NamedDBElement;
use App\Entity\Base\StructuralDBElement;
use App\Helpers\Trees\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;
use Symfony\Contracts\Translation\TranslatorInterface;
/**
* This service gives you a flat list containing all structured entities in the order of the structure.
*/
class NodesListBuilder
{
protected $em;
protected $cache;
protected $keyGenerator;
public function __construct( EntityManagerInterface $em, TagAwareCacheInterface $treeCache, UserCacheKeyGenerator $keyGenerator)
{
$this->em = $em;
$this->keyGenerator = $keyGenerator;
$this->cache = $treeCache;
}
/**
* Gets a flattened hierachical tree. Useful for generating option lists.
* In difference to the Repository Function, the results here are cached.
*
* @param string $class_name The class name of the entity you want to retrieve.
* @param StructuralDBElement|null $parent This entity will be used as root element. Set to null, to use global root
*
* @return StructuralDBElement[] A flattened list containing the tree elements.
*/
public function typeToNodesList(string $class_name, ?StructuralDBElement $parent = null): array
{
$parent_id = null != $parent ? $parent->getID() : '0';
// Backslashes are not allowed in cache keys
$secure_class_name = str_replace('\\', '_', $class_name);
$key = 'list_'.$this->keyGenerator->generateKey().'_'.$secure_class_name.$parent_id;
$ret = $this->cache->get($key, function (ItemInterface $item) use ($class_name, $parent, $secure_class_name) {
// Invalidate when groups, a element with the class or the user changes
$item->tag(['groups', 'tree_list', $this->keyGenerator->generateKey(), $secure_class_name]);
/**
* @var StructuralDBElementRepository
*/
$repo = $this->em->getRepository($class_name);
return $repo->toNodesList($parent);
});
return $ret;
}
}

View file

@ -19,7 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
namespace App\Services;
namespace App\Services\Trees;
use App\Entity\Attachments\AttachmentType;
use App\Entity\Attachments\PartAttachment;
@ -34,7 +34,8 @@ use App\Entity\Parts\Supplier;
use App\Entity\PriceInformations\Currency;
use App\Entity\UserSystem\Group;
use App\Entity\UserSystem\User;
use App\Helpers\TreeViewNode;
use App\Helpers\Trees\TreeViewNode;
use App\Services\UserCacheKeyGenerator;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Security;
use Symfony\Contracts\Cache\ItemInterface;

View file

@ -23,15 +23,17 @@ namespace App\Services\Trees;
use App\Entity\Base\DBElement;
use App\Entity\Base\NamedDBElement;
use App\Entity\Base\StructuralDBElement;
use App\Helpers\Trees\TreeViewNodeIterator;
use App\Helpers\TreeViewNode;
use App\Helpers\Trees\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;
use Symfony\Contracts\Translation\TranslatorInterface;
class TreeViewGenerator
{
@ -40,21 +42,51 @@ class TreeViewGenerator
protected $em;
protected $cache;
protected $keyGenerator;
protected $translator;
public function __construct(EntityURLGenerator $URLGenerator, EntityManagerInterface $em,
TagAwareCacheInterface $treeCache, UserCacheKeyGenerator $keyGenerator)
TagAwareCacheInterface $treeCache, UserCacheKeyGenerator $keyGenerator, TranslatorInterface $translator)
{
$this->urlGenerator = $URLGenerator;
$this->em = $em;
$this->cache = $treeCache;
$this->keyGenerator = $keyGenerator;
$this->translator = $translator;
}
public function getTreeView(string $class, ?StructuralDBElement $parent = null, string $href_type = 'list_parts', DBElement $selectedElement = null)
/**
* Gets a TreeView list for the entities of the given class.
* @param string $class The class for which the treeView should be generated
* @param StructuralDBElement|null $parent The root nodes in the tree should have this element as parent (use null, if you want to get all entities)
* @param string $href_type The link type that will be generated for the hyperlink section of each node (see EntityURLGenerator for possible values).
* Set to empty string, to disable href field.
* @param DBElement|null $selectedElement The element that should be selected. If set to null, no element will be selected.
* @return TreeViewNode[] An array of TreeViewNode[] elements of the root elements.
*/
public function getTreeView(string $class, ?StructuralDBElement $parent = null, string $href_type = 'list_parts', DBElement $selectedElement = null) : array
{
$head = [];
//When we use the newEdit type, add the New Element node.
if ('newEdit' === $href_type) {
//Generate the url for the new node
$href = $this->urlGenerator->createURL(new $class());
$new_node = new TreeViewNode($this->translator->trans('entity.tree.new'), $href);
//When the id of the selected element is null, then we have a new element, and we need to select "new" node
if (null == $selectedElement || null == $selectedElement->getID()) {
$new_node->setSelected(true);
}
$head[] = $new_node;
//Add spacing
$head[] = (new TreeViewNode(''))->setDisabled(true);
//Every other treeNode will be used for edit
$href_type = 'edit';
}
$generic = $this->getGenericTree($class, $parent);
$treeIterator = new TreeViewNodeIterator($generic);
$recursiveIterator = new \RecursiveIteratorIterator($treeIterator);
$recursiveIterator = new \RecursiveIteratorIterator($treeIterator, \RecursiveIteratorIterator::SELF_FIRST);
foreach ($recursiveIterator as $item) {
/** @var $item TreeViewNode */
if ($selectedElement !== null && $item->getId() === $selectedElement->getID()) {
@ -71,7 +103,7 @@ class TreeViewGenerator
}
}
return $generic;
return array_merge($head, $generic);
}
/**
@ -85,11 +117,11 @@ class TreeViewGenerator
*/
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(!is_a($class, NamedDBElement::class, true)) {
throw new \InvalidArgumentException('$class must be a class string that implements StructuralDBElement or NamedDBElement!');
}
if($parent !== null && !is_a($parent, $class)) {
throw new \InvalidArgumentException('$parent must be of the type class!');
throw new \InvalidArgumentException('$parent must be of the type $class!');
}
/** @var StructuralDBElementRepository $repo */

View file

@ -31,7 +31,8 @@ use App\Services\FAIconGenerator;
use App\Services\MarkdownParser;
use App\Services\MoneyFormatter;
use App\Services\SIFormatter;
use App\Services\TreeBuilder;
use App\Services\Trees\NodesListBuilder;
use App\Services\Trees\TreeViewGenerator;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use Twig\Extension\AbstractExtension;
@ -53,7 +54,7 @@ class AppExtension extends AbstractExtension
protected $translator;
public function __construct(EntityURLGenerator $entityURLGenerator, MarkdownParser $markdownParser,
SerializerInterface $serializer, TreeBuilder $treeBuilder,
SerializerInterface $serializer, TreeViewGenerator $treeBuilder,
MoneyFormatter $moneyFormatter,
SIFormatter $SIFormatter, AmountFormatter $amountFormatter,
AttachmentURLGenerator $attachmentURLGenerator,
@ -103,7 +104,7 @@ class AppExtension extends AbstractExtension
public function treeData(DBElement $element, string $type = 'newEdit'): string
{
$tree = $this->treeBuilder->typeToTree(\get_class($element), $type, $element);
$tree = $this->treeBuilder->getTreeView(\get_class($element), null, $type, $element);
return $this->serializer->serialize($tree, 'json', ['skip_null_values' => true]);
}

View file

@ -21,7 +21,7 @@
namespace App\Tests\Helpers;
use App\Helpers\TreeViewNode;
use App\Helpers\Trees\TreeViewNode;
use PHPUnit\Framework\TestCase;
class TreeViewNodeTest extends TestCase

View file

@ -23,7 +23,7 @@ namespace App\Tests\Repository;
use App\Entity\Attachments\AttachmentType;
use App\Entity\UserSystem\User;
use App\Helpers\TreeViewNode;
use App\Helpers\Trees\TreeViewNode;
use App\Repository\NamedDBElementRepository;
use App\Repository\StructuralDBElementRepository;
use PHPUnit\Framework\TestCase;

View file

@ -22,7 +22,7 @@
namespace App\Tests\Repository;
use App\Entity\Attachments\AttachmentType;
use App\Helpers\TreeViewNode;
use App\Helpers\Trees\TreeViewNode;
use App\Repository\StructuralDBElementRepository;
use PHPUnit\Framework\TestCase;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

View file

@ -0,0 +1,80 @@
<?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\Services\Trees\NodesListBuilder;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
/**
* @Group DB
* @package App\Tests\Services\Trees
*/
class NodesListBuilderTest extends WebTestCase
{
/**
* @var NodesListBuilder $service
*/
protected $service;
protected $em;
public function setUp(): void
{
self::bootKernel();
$this->service = self::$container->get(NodesListBuilder::class);
$this->em = self::$container->get(EntityManagerInterface::class);
}
/**
* Test $repo->toNodesList() for null as parameter
*/
public function testTypeToNodesListtRoot() : void
{
//List all root nodes and their children
$nodes = $this->service->typeToNodesList(AttachmentType::class);
$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 testTypeToNodesListElement() : void
{
//List all nodes that are children to Node 1
$node1 = $this->em->find(AttachmentType::class, 1);
$nodes = $this->service->typeToNodesList(AttachmentType::class, $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

@ -22,21 +22,24 @@
namespace App\Tests\Services\Trees;
use App\Entity\Attachments\AttachmentType;
use App\Helpers\TreeViewNode;
use App\Entity\Parts\Category;
use App\Helpers\Trees\TreeViewNode;
use App\Services\AmountFormatter;
use App\Services\Trees\TreeViewGenerator;
use Doctrine\ORM\EntityManagerInterface;
use PHPUnit\Framework\TestCase;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
/**
* @group DB
*/
class TreeGeneratorTest extends WebTestCase
class TreeViewGeneratorTest extends WebTestCase
{
/**
* @var TreeViewGenerator
*/
protected $service;
protected $em;
public function setUp() : void
{
@ -45,6 +48,7 @@ class TreeGeneratorTest extends WebTestCase
//Get an service instance.
self::bootKernel();
$this->service = self::$container->get(TreeViewGenerator::class);
$this->em = self::$container->get(EntityManagerInterface::class);
}
public function testGetGenericTree()
@ -71,6 +75,49 @@ class TreeGeneratorTest extends WebTestCase
$this->assertEquals(1, $tree[0]->getId());
$this->assertEquals(2, $tree[1]->getId());
$this->assertEquals(7, $tree[0]->getNodes()[0]->getNodes()[0]->getId());
}
public function testGetTreeViewBasic()
{
$tree = $this->service->getTreeView(Category::class);
$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());
//Assert that the nodes contain the correct links
$this->assertEquals('/en/category/1/parts', $tree[0]->getHref());
$this->assertEquals('/en/category/2/parts', $tree[1]->getHref());
$this->assertEquals('/en/category/7/parts', $tree[0]->getNodes()[0]->getNodes()[0]->getHref());
}
public function testGetTreeViewNewEdit()
{
$tree = $this->service->getTreeView(Category::class, null, 'newEdit');
//First element should link to new category
$this->assertStringContainsStringIgnoringCase('New', $tree[0]->getText());
$this->assertEquals('/en/category/new', $tree[0]->getHref());
//By default the new element node is selected
$this->assertTrue($tree[0]->getState()->getSelected());
//Next element is spacing
$this->assertEquals('', $tree[1]->getText());
$this->assertTrue($tree[1]->getState()->getDisabled());
//All other elements should be normal
$this->assertCount(5, $tree);
}
public function testGetTreeViewSelectedNode()
{
$selected = $this->em->find(Category::class, 2);
$tree = $this->service->getTreeView(Category::class, null, 'edit', $selected);
$this->assertNull($tree[0]->getState());
//Only second element must be selected
$this->assertTrue($tree[1]->getState()->getSelected());
}
}