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')); } } }