/** * Determine if this campaign applies * * @param $eventDetails * @param $event * * @return bool */ public static function validateEmailTrigger(Email $eventDetails = null, $event) { if ($eventDetails == null) { return false; } //check to see if the parent event is a "send email" event and that it matches the current email opened if (!empty($event['parent']) && $event['parent']['type'] == 'email.send') { return $eventDetails->getId() === (int) $event['parent']['properties']['email']; } return false; }
/** * Gets template, stats, weights, etc for an email in preparation to be sent * * @param Email $email * @param bool $includeVariants * * @return array */ public function getEmailSettings(Email $email, $includeVariants = true) { static $emailSettings = array(); if (empty($emailSettings[$email->getId()])) { //used to house slots so they don't have to be fetched over and over for same template $slots = array(); $template = $email->getTemplate(); $slots[$template] = $this->factory->getTheme($template)->getSlots('email'); //store the settings of all the variants in order to properly disperse the emails //set the parent's settings $emailSettings = array($email->getId() => array('template' => $email->getTemplate(), 'slots' => $slots, 'sentCount' => $email->getSentCount(), 'variantCount' => $email->getVariantSentCount(), 'entity' => $email)); if ($includeVariants) { //get a list of variants for A/B testing $childrenVariant = $email->getVariantChildren(); if (count($childrenVariant)) { $variantWeight = 0; $totalSent = $email->getVariantSentCount(); foreach ($childrenVariant as $id => $child) { if ($child->isPublished()) { $template = $child->getTemplate(); if (isset($slots[$template])) { $useSlots = $slots[$template]; } else { $slots[$template] = $this->factory->getTheme($template)->getSlots('email'); $useSlots = $slots[$template]; } $variantSettings = $child->getVariantSettings(); $emailSettings[$child->getId()] = array('template' => $child->getTemplate(), 'slots' => $useSlots, 'sentCount' => $child->getSentCount(), 'variantCount' => $child->getVariantSentCount(), 'weight' => $variantSettings['weight'] / 100, 'entity' => $child); $variantWeight += $variantSettings['weight']; $totalSent += $emailSettings[$child->getId()]['sentCount']; } } //set parent weight $emailSettings[$email->getId()]['weight'] = (100 - $variantWeight) / 100; //now find what percentage of current leads should receive the variants foreach ($emailSettings as $eid => &$details) { $details['weight'] = $totalSent ? $details['weight'] - $details['variantCount'] / $totalSent + $details['weight'] : $details['weight']; } } else { $emailSettings[$email->getId()]['weight'] = 1; } } } return $emailSettings; }
/** * {@inheritDoc} */ public function getId() { if ($this->__isInitialized__ === false) { return (int) parent::getId(); } $this->__initializer__ && $this->__initializer__->__invoke($this, 'getId', array()); return parent::getId(); }
/** * Gets template, stats, weights, etc for an email in preparation to be sent * * @param Email $email * @param bool $includeVariants * * @return array */ public function &getEmailSettings(Email $email, $includeVariants = true) { if (empty($this->emailSettings[$email->getId()])) { //used to house slots so they don't have to be fetched over and over for same template // BC for Mautic v1 templates $slots = []; if ($template = $email->getTemplate()) { $slots[$template] = $this->themeHelper->getTheme($template)->getSlots('email'); } //store the settings of all the variants in order to properly disperse the emails //set the parent's settings $emailSettings = [$email->getId() => ['template' => $email->getTemplate(), 'slots' => $slots, 'sentCount' => $email->getSentCount(), 'variantCount' => $email->getVariantSentCount(), 'isVariant' => null !== $email->getVariantStartDate(), 'entity' => $email, 'translations' => $email->getTranslations(true), 'languages' => ['default' => $email->getId()]]]; if ($emailSettings[$email->getId()]['translations']) { // Add in the sent counts for translations of this email /** @var Email $translation */ foreach ($emailSettings[$email->getId()]['translations'] as $translation) { if ($translation->isPublished()) { $emailSettings[$email->getId()]['sentCount'] += $translation->getSentCount(); $emailSettings[$email->getId()]['variantCount'] += $translation->getVariantSentCount(); // Prevent empty key due to misconfiguration - pretty much ignored if (!($language = $translation->getLanguage())) { $language = 'unknown'; } $core = $this->getTranslationLocaleCore($language); if (!isset($emailSettings[$email->getId()]['languages'][$core])) { $emailSettings[$email->getId()]['languages'][$core] = []; } $emailSettings[$email->getId()]['languages'][$core][$language] = $translation->getId(); } } } if ($includeVariants && $email->isVariant()) { //get a list of variants for A/B testing $childrenVariant = $email->getVariantChildren(); if (count($childrenVariant)) { $variantWeight = 0; $totalSent = $emailSettings[$email->getId()]['variantCount']; foreach ($childrenVariant as $id => $child) { if ($child->isPublished()) { $useSlots = []; if ($template = $child->getTemplate()) { if (isset($slots[$template])) { $useSlots = $slots[$template]; } else { $slots[$template] = $this->themeHelper->getTheme($template)->getSlots('email'); $useSlots = $slots[$template]; } } $variantSettings = $child->getVariantSettings(); $emailSettings[$child->getId()] = ['template' => $child->getTemplate(), 'slots' => $useSlots, 'sentCount' => $child->getSentCount(), 'variantCount' => $child->getVariantSentCount(), 'isVariant' => null !== $email->getVariantStartDate(), 'weight' => $variantSettings['weight'] / 100, 'entity' => $child, 'translations' => $child->getTranslations(true), 'languages' => ['default' => $child->getId()]]; $variantWeight += $variantSettings['weight']; if ($emailSettings[$child->getId()]['translations']) { // Add in the sent counts for translations of this email /** @var Email $translation */ foreach ($emailSettings[$child->getId()]['translations'] as $translation) { if ($translation->isPublished()) { $emailSettings[$child->getId()]['sentCount'] += $translation->getSentCount(); $emailSettings[$child->getId()]['variantCount'] += $translation->getVariantSentCount(); // Prevent empty key due to misconfiguration - pretty much ignored if (!($language = $translation->getLanguage())) { $language = 'unknown'; } $core = $this->getTranslationLocaleCore($language); if (!isset($emailSettings[$child->getId()]['languages'][$core])) { $emailSettings[$child->getId()]['languages'][$core] = []; } $emailSettings[$child->getId()]['languages'][$core][$language] = $translation->getId(); } } } $totalSent += $emailSettings[$child->getId()]['variantCount']; } } //set parent weight $emailSettings[$email->getId()]['weight'] = (100 - $variantWeight) / 100; } else { $emailSettings[$email->getId()]['weight'] = 1; } } $this->emailSettings[$email->getId()] = $emailSettings; } if ($includeVariants && $email->isVariant()) { //now find what percentage of current leads should receive the variants if (!isset($totalSent)) { $totalSent = 0; foreach ($this->emailSettings[$email->getId()] as $eid => $details) { $totalSent += $details['variantCount']; } } foreach ($this->emailSettings[$email->getId()] as $eid => &$details) { // Determine the deficit for email ordering if ($totalSent) { $details['weight_deficit'] = $details['weight'] - $details['variantCount'] / $totalSent; $details['send_weight'] = $details['weight'] - $details['variantCount'] / $totalSent + $details['weight']; } else { $details['weight_deficit'] = $details['weight']; $details['send_weight'] = $details['weight']; } } // Reorder according to send_weight so that campaigns which currently send one at a time alternate uasort($this->emailSettings[$email->getId()], function ($a, $b) { if ($a['weight_deficit'] === $b['weight_deficit']) { if ($a['variantCount'] === $b['variantCount']) { return 0; } // if weight is the same - sort by least number sent return $a['variantCount'] < $b['variantCount'] ? -1 : 1; } // sort by the one with the greatest deficit first return $a['weight_deficit'] > $b['weight_deficit'] ? -1 : 1; }); } return $this->emailSettings[$email->getId()]; }
/** * Create an email stat. * * @param bool|true $persist * @param string|null $emailAddress * @param null $listId * * @return Stat|void * * @throws \Doctrine\ORM\ORMException */ public function createEmailStat($persist = true, $emailAddress = null, $listId = null) { static $copies = []; //create a stat $stat = new Stat(); $stat->setDateSent(new \DateTime()); $stat->setEmail($this->email); // Note if a lead if (null !== $this->lead) { $stat->setLead($this->factory->getEntityManager()->getReference('MauticLeadBundle:Lead', $this->lead['id'])); $emailAddress = $this->lead['email']; } // Find email if applicable if (null === $emailAddress) { // Use the last address set $emailAddresses = $this->message->getTo(); if (count($emailAddresses)) { end($emailAddresses); $emailAddress = key($emailAddresses); } } $stat->setEmailAddress($emailAddress); // Note if sent from a lead list if (null !== $listId) { $stat->setList($this->factory->getEntityManager()->getReference('MauticLeadBundle:LeadList', $listId)); } $stat->setTrackingHash($this->idHash); if (!empty($this->source)) { $stat->setSource($this->source[0]); $stat->setSourceId($this->source[1]); } $stat->setTokens($this->getTokens()); /** @var \Mautic\EmailBundle\Model\EmailModel $emailModel */ $emailModel = $this->factory->getModel('email'); // Save a copy of the email - use email ID if available simply to prevent from having to rehash over and over $id = null !== $this->email ? $this->email->getId() : md5($this->subject . $this->body['content']); if (!isset($copies[$id])) { $hash = strlen($id) !== 32 ? md5($this->subject . $this->body['content']) : $id; $copy = $emailModel->getCopyRepository()->findByHash($hash); $copyCreated = false; if (null === $copy) { if (!$emailModel->getCopyRepository()->saveCopy($hash, $this->subject, $this->body['content'])) { // Try one more time to find the ID in case there was overlap when creating $copy = $emailModel->getCopyRepository()->findByHash($hash); } else { $copyCreated = true; } } if ($copy || $copyCreated) { $copies[$id] = $hash; } } if (isset($copies[$id])) { $stat->setStoredCopy($this->factory->getEntityManager()->getReference('MauticEmailBundle:Copy', $copies[$id])); } if ($persist) { $emailModel->getStatRepository()->saveEntity($stat); } return $stat; }