Added possibility to import categories and footprints

This commit is contained in:
Jan Böhmer 2023-03-24 22:41:33 +01:00
parent fce32e70b9
commit 34aefd32e8
2 changed files with 145 additions and 1 deletions

View file

@ -91,6 +91,14 @@ class ImportPartKeeprCommand extends Command
$io->info('Importing manufacturers...');
$count = $this->importer->importManufacturers($data);
$io->success('Imported '.$count.' manufacturers.');
$io->info('Importing categories...');
$count = $this->importer->importCategories($data);
$io->success('Imported '.$count.' categories.');
$io->info('Importing Footprints...');
$count = $this->importer->importFootprints($data);
$io->success('Imported '.$count.' footprints.');
}
}

View file

@ -23,6 +23,9 @@ namespace App\Services\ImportExportSystem;
use App\Doctrine\Purger\ResetAutoIncrementORMPurger;
use App\Doctrine\Purger\ResetAutoIncrementPurgerFactory;
use App\Entity\Base\AbstractDBElement;
use App\Entity\Base\AbstractStructuralDBElement;
use App\Entity\Parts\Category;
use App\Entity\Parts\Footprint;
use App\Entity\Parts\Manufacturer;
use App\Entity\Parts\MeasurementUnit;
use App\Entity\Parts\Part;
@ -144,8 +147,141 @@ class PartkeeprImporter
return count($partunit_data);
}
public function setIDOfEntity(AbstractDBElement $element, int $id): void
public function importCategories(array $data): int
{
if (!isset($data['partcategory'])) {
throw new \RuntimeException('$data must contain a "partcategory" key!');
}
$partcategory_data = $data['partcategory'];
//In a first step, create all categories like they were a flat structure (so ignore the parent)
foreach ($partcategory_data as $partcategory) {
$category = new Category();
$category->setName($partcategory['name']);
$category->setComment($partcategory['description']);
$this->setIDOfEntity($category, $partcategory['id']);
$this->em->persist($category);
}
$this->em->flush();
//In a second step, set the correct parent element
foreach ($partcategory_data as $partcategory) {
$this->setParent(Category::class, $partcategory['id'], $partcategory['parent_id']);
}
$this->em->flush();
return count($partcategory_data);
}
private function importElementsWithCategory(array $data, string $target_class, string $data_prefix): int
{
}
public function importFootprints(array $data): int
{
if (!isset($data['footprint'])) {
throw new \RuntimeException('$data must contain a "footprint" key!');
}
if (!isset($data['footprintcategory'])) {
throw new \RuntimeException('$data must contain a "footprintcategory" key!');
}
//We import the footprints first, as we need the IDs of the footprints be our real DBs later (as we match the part import by ID)
//As the footprints category is not existing yet, we just skip the parent field for now
$footprint_data = $data['footprint'];
$max_footprint_id = 0;
foreach ($footprint_data as $footprint) {
$entity = new Footprint();
$entity->setName($footprint['name']);
$entity->setComment($footprint['description']);
$this->setIDOfEntity($entity, $footprint['id']);
$this->em->persist($entity);
$max_footprint_id = max($max_footprint_id, (int) $footprint['id']);
}
//Import the footprint categories ignoring the parents for now
//Their IDs are $max_footprint_id + $ID
$footprintcategory_data = $data['footprintcategory'];
foreach ($footprintcategory_data as $footprintcategory) {
$entity = new Footprint();
$entity->setName($footprintcategory['name']);
$entity->setComment($footprintcategory['description']);
//Categories are not assignable to parts, so we set them to not selectable
$entity->setNotSelectable(true);
$this->setIDOfEntity($entity, $max_footprint_id + (int) $footprintcategory['id']);
$this->em->persist($entity);
}
$this->em->flush();
//Now we can correct the parents and category IDs of the parts
foreach ($footprintcategory_data as $footprintcategory) {
//We have to use the mapped IDs here, as the imported ID is not the effective ID
if ($footprintcategory['parent_id']) {
$this->setParent(Footprint::class, $max_footprint_id + (int)$footprintcategory['id'],
$max_footprint_id + (int)$footprintcategory['parent_id']);
}
}
foreach ($footprint_data as $footprint) {
if ($footprint['category_id']) {
$this->setParent(Footprint::class, $footprint['id'],
$max_footprint_id + (int)$footprint['category_id']);
}
}
$this->em->flush();
return count($footprint_data) + count($footprintcategory_data);
}
/**
* Assigns the parent to the given entity, using the numerical IDs from the imported data.
* @param string $class
* @param int|string $element_id
* @param int|string $parent_id
* @return AbstractStructuralDBElement The structural element that was modified (with $element_id)
*/
private function setParent(string $class, $element_id, $parent_id): AbstractStructuralDBElement
{
$element = $this->em->find($class, (int) $element_id);
if (!$element) {
throw new \RuntimeException(sprintf('Could not find element with ID %s', $element_id));
}
//If the parent is null, we're done
if (!$parent_id) {
return $element;
}
$parent = $this->em->find($class, (int) $parent_id);
if (!$parent) {
throw new \RuntimeException(sprintf('Could not find parent with ID %s', $parent_id));
}
$element->setParent($parent);
return $element;
}
/**
* Set the ID of an entity to a specific value. Must be called before persisting the entity, but before flushing.
* @param AbstractDBElement $element
* @param int|string $id
* @return void
*/
public function setIDOfEntity(AbstractDBElement $element, $id): void
{
if (!is_int($id) && !is_string($id)) {
throw new \InvalidArgumentException('ID must be an integer or string');
}
$id = (int) $id;
$metadata = $this->em->getClassMetadata(get_class($element));
$metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_NONE);
$metadata->setIdGenerator(new \Doctrine\ORM\Id\AssignedGenerator());