Merge the remaining fields of a Part

This commit is contained in:
Jan Böhmer 2023-11-21 19:41:18 +01:00
parent 478d5e2a3a
commit c86694ab8f
4 changed files with 384 additions and 4 deletions

View file

@ -25,6 +25,7 @@ namespace App\Services\EntityMergers\Mergers;
use App\Entity\Attachments\Attachment;
use App\Entity\Attachments\AttachmentContainingDBElement;
use App\Entity\Base\AbstractNamedDBElement;
use App\Entity\Base\AbstractStructuralDBElement;
use App\Entity\Parameters\AbstractParameter;
use App\Entity\Parts\Part;
@ -33,6 +34,8 @@ use Doctrine\Common\Collections\Collection;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
use Symfony\Contracts\Service\Attribute\Required;
use function Symfony\Component\String\u;
/**
* This trait provides helper methods for entity mergers.
* By default, it uses the value from the target entity, unless it not fullfills a condition.
@ -184,10 +187,10 @@ trait EntityMergerHelperTrait
protected function mergeTags(object $target, object $other, string $field, string $separator = ','): object
{
return $this->useCallback(
function (string $t, string $o) use ($separator): string {
function (string|null $t, string|null $o) use ($separator): string {
//Explode the strings into arrays
$t_array = explode($separator, $t);
$o_array = explode($separator, $o);
$t_array = explode($separator, $t ?? '');
$o_array = explode($separator, $o ?? '');
//Merge the arrays and remove duplicates
$tmp = array_unique(array_merge($t_array, $o_array));
@ -281,4 +284,75 @@ trait EntityMergerHelperTrait
&& $t->getGroup() === $o->getGroup();
});
}
/**
* Check if the two strings have equal content.
* This method is case-insensitive and ignores whitespace.
* @param string|\Stringable $t
* @param string|\Stringable $o
* @return bool
*/
protected function areStringsEqual(string|\Stringable $t, string|\Stringable $o): bool
{
$t_str = u($t)->trim()->folded();
$o_str = u($o)->trim()->folded();
return $t_str->equalsTo($o_str);
}
/**
* Merge the text from the target and the other entity for the given field by attaching the other text to the target text via the given separator.
* For example, if the target text is "Hello" and the other text is "World", the result is "Hello / World".
* If the text is the same in both entities, the target text is returned.
* @param object $target
* @param object $other
* @param string $field
* @param string $separator
* @return object
*/
protected function mergeTextWithSeparator(object $target, object $other, string $field, string $separator = ' / '): object
{
return $this->useCallback(
function (string $t, string $o) use ($separator): string {
//Check if the strings are equal
if ($this->areStringsEqual($t, $o)) {
return $t;
}
return trim($t) . $separator . trim($o);
},
$target,
$other,
$field
);
}
/**
* Merge two comments from the target and the other entity for the given field.
* The comments of the both entities get concated, while the second part get a headline with the name of the old part.
* @param AbstractNamedDBElement $target
* @param AbstractNamedDBElement $other
* @param string $field
* @return object
*/
protected function mergeComment(AbstractNamedDBElement $target, AbstractNamedDBElement $other, string $field = 'comment'): object
{
return $this->useCallback(
function (string $t, string $o) use ($other): string {
//Check if the strings are equal
if ($this->areStringsEqual($t, $o)) {
return $t;
}
return sprintf("%s\n\n<b>%s:</b>\n%s",
trim($t),
$other->getName(),
trim($o)
);
},
$target,
$other,
$field
);
}
}

View file

@ -23,6 +23,8 @@ declare(strict_types=1);
namespace App\Services\EntityMergers\Mergers;
use App\Entity\Parts\InfoProviderReference;
use App\Entity\Parts\ManufacturingStatus;
use App\Entity\Parts\Part;
use App\Entity\Parts\PartAssociation;
use App\Entity\Parts\PartLot;
@ -46,7 +48,16 @@ class PartMerger implements EntityMergerInterface
throw new \InvalidArgumentException('The target and the other entity must be instances of Part');
}
//Merge basic infos
//Merge basic fields
$this->mergeTextWithSeparator($target, $other, 'name');
$this->mergeTextWithSeparator($target, $other, 'description');
$this->mergeComment($target, $other);
$this->useOtherValueIfNotEmtpy($target, $other, 'manufacturer_product_url');
$this->useOtherValueIfNotEmtpy($target, $other, 'manufacturer_product_number');
$this->useOtherValueIfNotEmtpy($target, $other, 'mass');
$this->useOtherValueIfNotEmtpy($target, $other, 'ipn');
//Merge relations to other entities
$this->useOtherValueIfNotNull($target, $other, 'manufacturer');
$this->useOtherValueIfNotNull($target, $other, 'footprint');
$this->useOtherValueIfNotNull($target, $other, 'category');
@ -62,6 +73,24 @@ class PartMerger implements EntityMergerInterface
//Merge the tags using the tag merger
$this->mergeTags($target, $other, 'tags');
//Merge manufacturing status
$this->useCallback(function (?ManufacturingStatus $t, ?ManufacturingStatus $o): ?ManufacturingStatus {
//Use the other value, if the target value is not set
if ($t === ManufacturingStatus::NOT_SET || $t === null) {
return $o ?? ManufacturingStatus::NOT_SET;
}
return $t;
}, $target, $other, 'manufacturing_status');
//Merge provider reference
$this->useCallback(function (InfoProviderReference $t, InfoProviderReference $o): InfoProviderReference {
if (!$t->isProviderCreated() && $o->isProviderCreated()) {
return $o;
}
return $t;
}, $target, $other, 'providerReference');
return $target;
}