Added possibility to create nested structures of elements using Mass Import

This commit is contained in:
Jan Böhmer 2023-01-28 23:24:45 +01:00
parent 22950f2476
commit 07f95bc6ea
7 changed files with 126 additions and 12 deletions

View file

@ -364,7 +364,7 @@ abstract class BaseAdminController extends AbstractController
//Create entries based on input
$errors = [];
$results = $importer->massCreation($data['lines'], $this->entity_class, $data['parent'], $errors);
$results = $importer->massCreation($data['lines'], $this->entity_class, $data['parent'] ?? null, $errors);
//Show errors to user:
foreach ($errors as $error) {

View file

@ -148,9 +148,20 @@ abstract class AbstractStructuralDBElement extends AttachmentContainingDBElement
return false;
}
//If this' parents element, is $another_element, then we are finished
return ($this->parent->getID() === $another_element->getID())
|| $this->parent->isChildOf($another_element); //Otherwise, check recursively
//If the parent element is equal to the element we want to compare, return true
if ($this->getParent()->getID() === null || $this->getParent()->getID() === null) {
//If the IDs are not yet defined, we have to compare the objects itself
if ($this->getParent() === $another_element) {
return true;
}
} else { //If the IDs are defined, we can compare the IDs
if ($this->getParent()->getID() === $another_element->getID()) {
return true;
}
}
//Otherwise, check recursively
return $this->parent->isChildOf($another_element);
}
/**

View file

@ -83,7 +83,7 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe
* @ORM\Column(type="string", name="config_theme", nullable=true)
* @Assert\Choice(choices=User::AVAILABLE_THEMES)
*/
protected ?string $theme = '';
protected ?string $theme = null;
/**
* @var string|null the hash of a token the user must provide when he wants to reset his password

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Services\ImportExportSystem;
use App\Entity\Base\AbstractNamedDBElement;
use App\Entity\Base\AbstractStructuralDBElement;
use function count;
use Doctrine\ORM\EntityManagerInterface;
@ -61,7 +62,7 @@ class EntityImporter
//Expand every line to a single entry:
$names = explode("\n", $lines);
if (!is_a($class_name, AbstractStructuralDBElement::class, true)) {
if (!is_a($class_name, AbstractNamedDBElement::class, true)) {
throw new InvalidArgumentException('$class_name must be a StructuralDBElement type!');
}
if (null !== $parent && !is_a($parent, $class_name)) {
@ -71,7 +72,31 @@ class EntityImporter
$errors = [];
$valid_entities = [];
$current_parent = $parent;
$last_element = $parent;
//We use this array to store all levels of indentation as a stack.
$indentations = [0];
foreach ($names as $name) {
//Count intendation level (whitespace characters at the beginning of the line)
$identSize = strlen($name)-strlen(ltrim($name));
//If the line is intendet more than the last line, we have a new parent element
if ($identSize > end($indentations)) {
$current_parent = $last_element;
//Add the new indentation level to the stack
$indentations[] = $identSize;
}
while ($identSize < end($indentations)) {
//If the line is intendet less than the last line, we have to go up in the tree
if ($current_parent instanceof AbstractStructuralDBElement) {
$current_parent = $current_parent->getParent();
} else {
$current_parent = null;
}
array_pop($indentations);
}
$name = trim($name);
if ('' === $name) {
//Skip empty lines (StrucuralDBElements must have a name)
@ -81,7 +106,10 @@ class EntityImporter
//Create new element with given name
$entity = new $class_name();
$entity->setName($name);
$entity->setParent($parent);
//Only set the parent if the entity is a StructuralDBElement
if ($entity instanceof AbstractStructuralDBElement) {
$entity->setParent($current_parent);
}
//Validate entity
$tmp = $this->validator->validate($entity);
@ -94,6 +122,8 @@ class EntityImporter
'violations' => $tmp,
];
}
$last_element = $entity;
}
return $valid_entities;