mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2025-06-21 17:39:06 +02:00
Allow to automatically find or create entities from database based on info providers
This commit is contained in:
parent
f9bce3dfdb
commit
6cd9640b30
4 changed files with 118 additions and 1 deletions
|
@ -22,6 +22,7 @@ declare(strict_types=1);
|
|||
*/
|
||||
namespace App\Form\Type\Helper;
|
||||
|
||||
use App\Entity\Base\AbstractStructuralDBElement;
|
||||
use App\Repository\StructuralDBElementRepository;
|
||||
use App\Services\Trees\NodesListBuilder;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
@ -32,13 +33,21 @@ class StructuralEntityChoiceLoader extends AbstractChoiceLoader
|
|||
{
|
||||
private ?string $additional_element = null;
|
||||
|
||||
private ?AbstractStructuralDBElement $starting_element = null;
|
||||
|
||||
public function __construct(private readonly Options $options, private readonly NodesListBuilder $builder, private readonly EntityManagerInterface $entityManager)
|
||||
{
|
||||
}
|
||||
|
||||
protected function loadChoices(): iterable
|
||||
{
|
||||
//If the starting_element is set and not persisted yet, add it to the list
|
||||
if ($this->starting_element !== null && $this->starting_element->getID() === null) {
|
||||
$tmp = [$this->starting_element];
|
||||
} else {
|
||||
$tmp = [];
|
||||
}
|
||||
|
||||
if ($this->additional_element) {
|
||||
$tmp = $this->createNewEntitiesFromValue($this->additional_element);
|
||||
$this->additional_element = null;
|
||||
|
@ -86,4 +95,23 @@ class StructuralEntityChoiceLoader extends AbstractChoiceLoader
|
|||
return $this->additional_element;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AbstractStructuralDBElement|null
|
||||
*/
|
||||
public function getStartingElement(): ?AbstractStructuralDBElement
|
||||
{
|
||||
return $this->starting_element;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AbstractStructuralDBElement|null $starting_element
|
||||
* @return StructuralEntityChoiceLoader
|
||||
*/
|
||||
public function setStartingElement(?AbstractStructuralDBElement $starting_element): StructuralEntityChoiceLoader
|
||||
{
|
||||
$this->starting_element = $starting_element;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -122,6 +122,11 @@ class StructuralEntityType extends AbstractType
|
|||
|
||||
public function modelTransform($value, array $options)
|
||||
{
|
||||
$choice_loader = $options['choice_loader'];
|
||||
if ($choice_loader instanceof StructuralEntityChoiceLoader) {
|
||||
$choice_loader->setStartingElement($value);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
|
|
|
@ -185,4 +185,69 @@ class StructuralDBElementRepository extends NamedDBElementRepository
|
|||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the element with the given name for the use with the InfoProvider System
|
||||
* The name search is a bit more fuzzy than the normal findByName, because it is case-insensitive and ignores special characters.
|
||||
* Also, it will try to find the element using the additional names field, of the elements.
|
||||
* @param string $name
|
||||
* @return AbstractStructuralDBElement|null
|
||||
*/
|
||||
public function findForInfoProvider(string $name): ?AbstractStructuralDBElement
|
||||
{
|
||||
//First try to find the element by name
|
||||
$qb = $this->createQueryBuilder('e');
|
||||
//Use lowercase conversion to be case-insensitive
|
||||
$qb->where($qb->expr()->like('LOWER(e.name)', 'LOWER(:name)'));
|
||||
|
||||
$qb->setParameter('name', $name);
|
||||
|
||||
$result = $qb->getQuery()->getResult();
|
||||
|
||||
if (count($result) === 1) {
|
||||
return $result[0];
|
||||
}
|
||||
|
||||
/*//If we have no result, try to find the element by additional names
|
||||
$qb = $this->createQueryBuilder('e');
|
||||
//Use lowercase conversion to be case-insensitive
|
||||
$qb->where($qb->expr()->like('LOWER(e.additional_names)', 'LOWER(:name)'));
|
||||
$qb->setParameter('name', '%'.$name.'%');
|
||||
|
||||
$result = $qb->getQuery()->getResult();
|
||||
|
||||
if (count($result) === 1) {
|
||||
return $result[0];
|
||||
}*/
|
||||
|
||||
//If we find nothing, return null
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to findForInfoProvider, but will create a new element with the given name if none was found.
|
||||
* @param string $name
|
||||
* @return AbstractStructuralDBElement
|
||||
*/
|
||||
public function findOrCreateForInfoProvider(string $name): AbstractStructuralDBElement
|
||||
{
|
||||
$entity = $this->findForInfoProvider($name);
|
||||
if (null === $entity) {
|
||||
|
||||
//Try to find if we already have an element cached for this name
|
||||
$entity = $this->getNewEntityFromCache($name, null);
|
||||
if ($entity) {
|
||||
return $entity;
|
||||
}
|
||||
|
||||
$class = $this->getClassName();
|
||||
/** @var AbstractStructuralDBElement $entity */
|
||||
$entity = new $class;
|
||||
$entity->setName($name);
|
||||
|
||||
$this->setNewEntityToCache($entity);
|
||||
}
|
||||
|
||||
return $entity;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,13 +25,16 @@ namespace App\Services\InfoProviderSystem;
|
|||
|
||||
use App\Entity\Attachments\AttachmentType;
|
||||
use App\Entity\Attachments\PartAttachment;
|
||||
use App\Entity\Base\AbstractStructuralDBElement;
|
||||
use App\Entity\Parameters\AbstractParameter;
|
||||
use App\Entity\Parameters\PartParameter;
|
||||
use App\Entity\Parts\Manufacturer;
|
||||
use App\Entity\Parts\ManufacturingStatus;
|
||||
use App\Entity\Parts\Part;
|
||||
use App\Services\InfoProviderSystem\DTOs\FileDTO;
|
||||
use App\Services\InfoProviderSystem\DTOs\ParameterDTO;
|
||||
use App\Services\InfoProviderSystem\DTOs\PartDetailDTO;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
/**
|
||||
* This class converts DTOs to entities which can be persisted in the DB
|
||||
|
@ -39,6 +42,10 @@ use App\Services\InfoProviderSystem\DTOs\PartDetailDTO;
|
|||
class DTOtoEntityConverter
|
||||
{
|
||||
|
||||
public function __construct(private readonly EntityManagerInterface $em)
|
||||
{
|
||||
}
|
||||
|
||||
public function convertParameter(ParameterDTO $dto, PartParameter $entity = new PartParameter()): PartParameter
|
||||
{
|
||||
$entity->setName($dto->name);
|
||||
|
@ -79,6 +86,8 @@ class DTOtoEntityConverter
|
|||
$entity->setDescription($dto->description ?? '');
|
||||
$entity->setComment($dto->notes ?? '');
|
||||
|
||||
$entity->setManufacturer($this->getOrCreateEntity(Manufacturer::class, $dto->manufacturer));
|
||||
|
||||
$entity->setManufacturerProductNumber($dto->mpn ?? '');
|
||||
$entity->setManufacturingStatus($dto->manufacturing_status ?? ManufacturingStatus::NOT_SET);
|
||||
|
||||
|
@ -95,4 +104,14 @@ class DTOtoEntityConverter
|
|||
return $entity;
|
||||
}
|
||||
|
||||
private function getOrCreateEntity(string $class, ?string $name): ?AbstractStructuralDBElement
|
||||
{
|
||||
//Fall through to make converting easier
|
||||
if ($name === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->em->getRepository($class)->findOrCreateForInfoProvider($name);
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue