Spaces:
No application file
No application file
namespace Mautic\CoreBundle\Model; | |
use Mautic\CoreBundle\Entity\TranslationEntityInterface; | |
use Mautic\CoreBundle\Entity\VariantEntityInterface; | |
trait VariantModelTrait | |
{ | |
/** | |
* @var bool | |
*/ | |
protected $inConversion = false; | |
/** | |
* Converts a variant to the main item and the original main item a variant. | |
*/ | |
public function convertVariant(VariantEntityInterface $entity): void | |
{ | |
// let saveEntities() know it does not need to set variant start dates | |
$this->inConversion = true; | |
[$parent, $children] = $entity->getVariants(); | |
$save = []; | |
// set this email as the parent for the original parent and children | |
if ($parent) { | |
if ($parent->getId() != $entity->getId()) { | |
if (method_exists($parent, 'setIsPublished')) { | |
$parent->setIsPublished(false); | |
} | |
$entity->addVariantChild($parent); | |
$parent->setVariantParent($entity); | |
} | |
$parent->setVariantStartDate(null); | |
$parent->setVariantSentCount(0); | |
foreach ($children as $child) { | |
// capture child before it's removed from collection | |
$save[] = $child; | |
$parent->removeVariantChild($child); | |
} | |
} | |
if (count($save)) { | |
foreach ($save as $child) { | |
if ($child->getId() != $entity->getId()) { | |
if (method_exists($child, 'setIsPublished')) { | |
$child->setIsPublished(false); | |
} | |
$entity->addVariantChild($child); | |
$child->setVariantParent($entity); | |
} else { | |
$child->removeVariantParent(); | |
} | |
$child->setVariantSentCount(0); | |
$child->setVariantStartDate(null); | |
} | |
} | |
$save[] = $parent; | |
$save[] = $entity; | |
// save the entities | |
$this->saveEntities($save, false); | |
} | |
/** | |
* Prepare a variant for saving. | |
* | |
* @param array $resetVariantCounterMethods ['setVariantHits', 'setVariantSends', ...] | |
*/ | |
protected function preVariantSaveEntity(VariantEntityInterface $entity, array $resetVariantCounterMethods = [], \DateTime $variantStartDate = null): bool | |
{ | |
$isVariant = $entity->isVariant(); | |
if (!$isVariant && $entity instanceof TranslationEntityInterface) { | |
// Translations could be assigned to a variant and thus applicable to be reset | |
if ($translationParent = $entity->getTranslationParent()) { | |
$isVariant = $translationParent->isVariant(); /** @phpstan-ignore-line @todo for M6, extend the TranslationEntityInterface from The VariantEntityInterface */ | |
} | |
} | |
if ($isVariant) { | |
// Reset the variant hit and start date if there are any changes and if this is an A/B test | |
// Do it here in addition to postVariantSave() so that it's available to the event listeners | |
$changes = $entity->getChanges(); | |
// If unpublished and wasn't changed from published - don't reset | |
if (!$entity->isPublished(false) && (!isset($changes['isPublished']))) { | |
return false; | |
} | |
// Reset the variant | |
if (!empty($changes) && empty($this->inConversion)) { | |
if (method_exists($entity, 'setVariantStartDate')) { | |
$entity->setVariantStartDate($variantStartDate); | |
} | |
// Reset counters | |
foreach ($resetVariantCounterMethods as $method) { | |
if (method_exists($entity, $method)) { | |
$entity->$method(0); | |
} | |
} | |
return true; | |
} | |
} | |
return false; | |
} | |
/** | |
* Run post saving a variant aware entity. | |
* | |
* @param bool $resetVariants | |
* @param array $relatedIds | |
*/ | |
protected function postVariantSaveEntity(VariantEntityInterface $entity, $resetVariants = false, $relatedIds = [], \DateTime $variantStartDate = null) | |
{ | |
// If parent, add this entity as a child of the parent so that it populates the list in the tab (due to Doctrine hanging on to entities in memory) | |
if ($parent = $entity->getVariantParent()) { | |
$parent->addVariantChild($entity); | |
} | |
// Reset associated variants if applicable due to changes | |
if ($resetVariants && empty($this->inConversion)) { | |
$this->resetVariants($entity, $relatedIds, $variantStartDate); | |
} | |
} | |
protected function resetVariants($entity, $relatedIds = null, \DateTime $variantStartDate = null) | |
{ | |
$repo = $this->getRepository(); | |
if (method_exists($repo, 'resetVariants')) { | |
if (null == $relatedIds) { | |
$relatedIds = $entity->getRelatedEntityIds(); | |
} | |
if (!in_array($entity->getId(), $relatedIds)) { | |
$relatedIds[] = $entity->getId(); | |
} | |
if (null === $variantStartDate) { | |
$variantStartDate = new \DateTime(); | |
} | |
// Ensure UTC since we're saving directly to the DB | |
$variantStartDate->setTimezone(new \DateTimeZone('UTC')); | |
$repo->resetVariants($relatedIds, $variantStartDate->format('Y-m-d H:i:s')); | |
} | |
} | |
} | |