Spaces:
No application file
No application file
namespace Mautic\CoreBundle\Entity; | |
use Doctrine\Common\Collections\ArrayCollection; | |
use Doctrine\Common\Collections\Collection; | |
use Doctrine\ORM\Mapping\Entity; | |
use Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder; | |
trait VariantEntityTrait | |
{ | |
/** | |
* @var mixed | |
**/ | |
private $variantChildren; | |
/** | |
* @var mixed | |
**/ | |
private $variantParent; | |
/** | |
* @var array | |
*/ | |
private $variantSettings = []; | |
/** | |
* @var \DateTimeInterface|null | |
*/ | |
private $variantStartDate; | |
/** | |
* @param ClassMetadata $builder | |
*/ | |
protected static function addVariantMetadata(ClassMetadataBuilder $builder, $entityClass) | |
{ | |
$builder->createManyToOne('variantParent', $entityClass) | |
->inversedBy('variantChildren') | |
->addJoinColumn('variant_parent_id', 'id', true, false, 'CASCADE') | |
->build(); | |
$builder->createOneToMany('variantChildren', $entityClass) | |
->setIndexBy('id') | |
->setOrderBy(['isPublished' => 'DESC']) | |
->mappedBy('variantParent') | |
->build(); | |
$builder->createField('variantSettings', 'array') | |
->columnName('variant_settings') | |
->nullable() | |
->build(); | |
$builder->createField('variantStartDate', 'datetime') | |
->columnName('variant_start_date') | |
->nullable() | |
->build(); | |
} | |
/** | |
* Add variant. | |
* | |
* @return $this | |
*/ | |
public function addVariantChild(VariantEntityInterface $child) | |
{ | |
if (!$this->variantChildren->contains($child)) { | |
$this->variantChildren[] = $child; | |
} | |
return $this; | |
} | |
/** | |
* Remove variant. | |
*/ | |
public function removeVariantChild(VariantEntityInterface $child): void | |
{ | |
$this->variantChildren->removeElement($child); | |
} | |
/** | |
* Get variantChildren. | |
* | |
* @return mixed | |
*/ | |
public function getVariantChildren() | |
{ | |
return $this->variantChildren; | |
} | |
/** | |
* Set variantParent. | |
* | |
* @param VarientEntityEnterface $parent | |
* | |
* @return $this | |
*/ | |
public function setVariantParent(VariantEntityInterface $parent = null) | |
{ | |
if (method_exists($this, 'isChanged')) { | |
$this->isChanged('variantParent', $parent); | |
} | |
$this->variantParent = $parent; | |
return $this; | |
} | |
/** | |
* Get variantParent. | |
* | |
* @return mixed | |
*/ | |
public function getVariantParent() | |
{ | |
return $this->variantParent; | |
} | |
/** | |
* Remove variant parent. | |
*/ | |
public function removeVariantParent(): void | |
{ | |
$this->setVariantParent(); | |
} | |
/** | |
* Set variantSettings. | |
* | |
* @param array $variantSettings | |
* | |
* @return $this | |
*/ | |
public function setVariantSettings($variantSettings) | |
{ | |
if (method_exists($this, 'isChanged')) { | |
$this->isChanged('variantSettings', $variantSettings); | |
} | |
$this->variantSettings = $variantSettings; | |
return $this; | |
} | |
/** | |
* Get variantSettings. | |
* | |
* @return array | |
*/ | |
public function getVariantSettings() | |
{ | |
return $this->variantSettings; | |
} | |
/** | |
* @return mixed | |
*/ | |
public function getVariantStartDate() | |
{ | |
return $this->variantStartDate; | |
} | |
/** | |
* @return $this | |
*/ | |
public function setVariantStartDate($variantStartDate) | |
{ | |
if (method_exists($this, 'isChanged')) { | |
$this->isChanged('variantStartDate', $variantStartDate); | |
} | |
$this->variantStartDate = $variantStartDate; | |
return $this; | |
} | |
/** | |
* @param bool $isChild True to return if the item is a variant of a parent | |
* | |
* @return bool | |
*/ | |
public function isVariant($isChild = false) | |
{ | |
$parent = $this->getVariantParent(); | |
$children = $this->getVariantChildren(); | |
if ($isChild) { | |
return (null === $parent) ? false : true; | |
} else { | |
return (!empty($parent) || count($children)) ? true : false; | |
} | |
} | |
/** | |
* Check if this entity has variants. | |
*/ | |
public function hasVariants(): int | |
{ | |
$children = $this->getTranslationChildren(); | |
return count($children); | |
} | |
/** | |
* Clear variants. | |
*/ | |
public function clearVariants(): void | |
{ | |
$this->variantChildren = new ArrayCollection(); | |
$this->variantParent = null; | |
} | |
/** | |
* Get the variant parent/children. | |
**. | |
* | |
* @return array<mixed> | |
*/ | |
public function getVariants(): array | |
{ | |
$parent = $this->getVariantParent(); | |
if (empty($parent)) { | |
$parent = $this; | |
} | |
if ($children = $parent->getVariantChildren()) { | |
if ($children instanceof Collection) { | |
$children = $children->toArray(); | |
} | |
} | |
if (!is_array($children)) { | |
$children = []; | |
} | |
return [$parent, $children]; | |
} | |
/** | |
* Get an array of all IDs for parent/child variants and associated translations if applicable. | |
* | |
* @param bool $publishedOnly | |
* | |
* @return array<int,int|string> | |
*/ | |
public function getRelatedEntityIds($publishedOnly = false): array | |
{ | |
[$parent, $children] = $this->getVariants(); | |
// If parent is not published and only published has been requested, no need to proceed | |
if ($parent && $publishedOnly && !$parent->isPublished()) { | |
return []; | |
} | |
// If this is a new top level entity, it may not have an ID | |
$ids = ($parent->getId()) ? [$parent->getId()] : []; | |
// Append translations for this variant if applicable | |
$this->appendTranslationEntityIds($this, $ids, $publishedOnly); | |
foreach ($children as $variant) { | |
if ((!$publishedOnly || $variant->isPublished()) && $id = $variant->getId()) { | |
$ids[] = $id; | |
// Append translations for this variant if applicable | |
$this->appendTranslationEntityIds($variant, $ids, $publishedOnly); | |
} | |
} | |
return array_unique($ids); | |
} | |
/** | |
* @return mixed | |
*/ | |
protected function getAccumulativeVariantCount($getter) | |
{ | |
[$parent, $children] = $this->getVariants(); | |
$count = $parent->$getter(); | |
if ($checkTranslations = method_exists($parent, 'getAccumulativeTranslationCount')) { | |
// Append translations for this variant if applicable | |
$count += $parent->getAccumulativeTranslationCount($getter, $parent); | |
} | |
foreach ($children as $variant) { | |
$count += $variant->$getter(); | |
if ($checkTranslations) { | |
// Append translations for this variant if applicable | |
$count += $variant->getAccumulativeTranslationCount($getter, $variant); | |
} | |
} | |
return $count; | |
} | |
/** | |
* Finds and appends IDs for translations of a variant. | |
*/ | |
protected function appendTranslationEntityIds($entity, &$ids, $publishedOnly) | |
{ | |
if (!($entity instanceof TranslationEntityInterface && method_exists($this, 'getTranslations'))) { | |
return; | |
} | |
/** @var TranslationEntityInterface $parentTranslation */ | |
/** @var ArrayCollection $childrenTranslations */ | |
[$parentTranslation, $childrenTranslations] = $entity->getTranslations(); | |
if ($entity->getId() && $parentTranslation != $entity) { | |
if (!$publishedOnly || $parentTranslation->isPublished()) { | |
$ids[] = $parentTranslation->getId(); | |
} | |
} | |
if (!$publishedOnly) { | |
if (is_array($childrenTranslations)) { | |
$ids = array_merge($ids, array_keys($childrenTranslations)); | |
} elseif ($childrenTranslations instanceof Collection) { | |
$ids = array_merge($ids, $childrenTranslations->getKeys()); | |
} | |
} else { | |
foreach ($childrenTranslations as $translation) { | |
if ($translation->isPublished() && $id = $translation->getId()) { | |
$ids[] = $id; | |
} | |
} | |
} | |
} | |
} | |