<?php
namespace App\AtechNet\CoreBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\JoinColumn;
use Doctrine\ORM\Mapping\JoinTable;
use Doctrine\ORM\Mapping\ManyToMany;
use Doctrine\ORM\Mapping\OrderBy;
use Doctrine\ORM\Mapping\Table as Table;
use Doctrine\ORM\PersistentCollection;
/**
* ConfigurableAttributeOptionCombination
*
* @Table(name="configurable_attribute_option_combinations")
* @Entity
*/
class ConfigurableAttributeOptionCombination extends AbstractSignedEntity
{
public const array ATTRIBUTE_ORDERING_MAP = [
V2Attribute::ID_RAM_INSTALLED_SIZE,
V2Attribute::ID_STORAGE_INSTALLED_SIZE,
V2Attribute::ID_STORAGE_INSTALLED_SIZE_SSD_HDD,
V2Attribute::ID_NEW_BATTERY,
V2Attribute::ID_GRADE
];
/**
* @var PersistentCollection
*
* @ManyToMany(targetEntity="V2AttributeOption", inversedBy="configurableAttributeOptionCombinations")
* @JoinTable(
* name="configurable_attribute_option_combinations_attribute_options",
* joinColumns={
* @JoinColumn(name="configurable_attribute_option_combination_id", referencedColumnName="id", onDelete="CASCADE")
* },
* inverseJoinColumns={
* @JoinColumn(name="v2_attribute_option_id", referencedColumnName="id")
* })
* @OrderBy({"created" = "DESC"})
*/
private $attributeOptions;
/**
* @var ArrayCollection
*
* @ManyToMany(targetEntity="ProductModel", mappedBy="configurableAttributeOptionCombinations")
* @OrderBy({"id" = "ASC"})
*/
private $productModels;
public function __construct()
{
parent::__construct();
$this->attributeOptions = new ArrayCollection();
}
/**
* @var string
*
* @Column(name="code", type="string", unique=true, nullable=true)
*/
private string $code;
/**
* @return PersistentCollection|null
*/
public function getAttributeOptions(): ?PersistentCollection
{
return $this->attributeOptions;
}
/**
* @param ArrayCollection $attributeOptions
*/
public function setAttributeOptions(ArrayCollection $attributeOptions)
{
$this->attributeOptions = $attributeOptions;
}
/**
* @param V2AttributeOption $attributeOption
*/
public function addAttributeOption($attributeOption)
{
if (!$this->attributeOptions->contains($attributeOption)) {
$this->attributeOptions->add($attributeOption);
}
}
/**
* @param V2AttributeOption $attributeOption
*/
public function removeItem($attributeOption)
{
$this->attributeOptions->removeElement($attributeOption);
}
/**
* @return ArrayCollection
*/
public function getSortedAttributeOptions(): ArrayCollection
{
$orderMap = array_flip(self::ATTRIBUTE_ORDERING_MAP);
$options = $this->getAttributeOptions()->toArray();
usort($options, function ($a, $b) use ($orderMap) {
$aKey = $orderMap[$a->getV2Attribute()->getId()] ?? null;
$bKey = $orderMap[$b->getV2Attribute()->getId()] ?? null;
if ($aKey !== null && $bKey !== null) {
return $aKey <=> $bKey;
}
if ($aKey !== null) {
return -1;
}
if ($bKey !== null) {
return 1;
}
return $a->getV2Attribute()->getId() <=> $b->getV2Attribute()->getId();
});
return new ArrayCollection($options);
}
/**
* @param string $separator
*
* @return string
*/
public function getSortedAttributeOptionsAsDisplayName(string $separator = '|'): string
{
$options = $this->getSortedAttributeOptions();
$displayNames = [];
/** @var V2AttributeOption $option */
foreach ($options as $option) {
$displayNames[] = $option->getDisplayFormattedValue();
}
return implode(" $separator ", $displayNames);
}
/**
* @return string
*/
public function getCode(): string
{
return $this->code;
}
/**
* @param string $code
* @return void
*/
public function setCode(string $code): void
{
$this->code = $code;
}
public function getOptionByAttributeId(int $v2AttributeId): ?V2AttributeOption
{
$result = $this->getAttributeOptions()->filter(
fn (V2AttributeOption $vao) => $vao->getV2Attribute()->getId() === $v2AttributeId
)->first();
return $result ?: null;
}
/**
* Returns options that differ between this and another combination, keyed by attribute ID.
* Each entry: ['self' => V2AttributeOption|null, 'other' => V2AttributeOption|null]
*
* @return array<int, array{self: V2AttributeOption|null, other: V2AttributeOption|null}>
*/
public function getDifferingOptions(ConfigurableAttributeOptionCombination $other): array
{
$selfMap = [];
$otherMap = [];
/** @var V2AttributeOption $option */
foreach ($this->getAttributeOptions() ?? [] as $option) {
$selfMap[$option->getV2Attribute()->getId()] = $option;
}
/** @var V2AttributeOption $option */
foreach ($other->getAttributeOptions() ?? [] as $option) {
$otherMap[$option->getV2Attribute()->getId()] = $option;
}
$allAttributeIds = array_unique(array_merge(array_keys($selfMap), array_keys($otherMap)));
$differences = [];
foreach ($allAttributeIds as $attrId) {
/** @var V2AttributeOption|null $selfOption */
$selfOption = $selfMap[$attrId] ?? null;
/** @var V2AttributeOption|null $otherOption */
$otherOption = $otherMap[$attrId] ?? null;
if ($selfOption?->getId() !== $otherOption?->getId()) {
$differences[$attrId] = [
'self' => $selfOption,
'other' => $otherOption,
];
}
}
return $differences;
}
/**
* @return array
*/
public function getAttributeOptionIds(): array
{
return $this->getAttributeOptions()->map(function ($option) {
return $option->getId();
})->toArray();
}
public function getProductModels()
{
return $this->productModels;
}
public function setProductModels($productModels): void
{
$this->productModels = $productModels;
}
}