/** * Determines the winner of A/B test based on dwell time rates * * @param MauticFactory $factory * @param Page $parent * @param $children * * @return array */ public static function determineDwellTimeTestWinner($factory, $parent, $children) { //find the hits that did not go any further $repo = $factory->getEntityManager()->getRepository('MauticPageBundle:Hit'); $pageIds = array($parent->getId()); foreach ($children as $c) { $pageIds[] = $c->getId(); } $startDate = $parent->getVariantStartDate(); if ($startDate != null && !empty($pageIds)) { //get their bounce rates $counts = $repo->getDwellTimes(array('pageIds' => $pageIds, 'startDate' => $startDate)); $translator = $factory->getTranslator(); $support = array(); if ($counts) { //in order to get a fair grade, we have to compare the averages here since a page that is only shown //25% of the time will have a significantly lower sum than a page shown 75% of the time $avgs = array(); $support['data'] = array(); $support['labels'] = array(); foreach ($counts as $pid => $stats) { $avgs[$pid] = $stats['average']; $support['data'][$translator->trans('mautic.page.abtest.label.dewlltime.average')][] = $stats['average']; $support['labels'][] = $pid . ':' . $stats['title']; } //set max for scales $max = max($avgs); $support['step_width'] = ceil($max / 10) * 10; //get the page ids with the greatest average dwell time $winners = $max > 0 ? array_keys($avgs, $max) : array(); return array('winners' => $winners, 'support' => $support, 'basedOn' => 'page.dwelltime', 'supportTemplate' => 'MauticPageBundle:SubscribedEvents\\AbTest:bargraph.html.php'); } } return array('winners' => array(), 'support' => array(), 'basedOn' => 'page.dwelltime'); }
/** * @param ObjectManager $manager */ public function load(ObjectManager $manager) { $factory = $this->container->get('mautic.factory'); $repo = $factory->getModel('page.page')->getRepository(); $pages = CsvHelper::csv_to_array(__DIR__ . '/fakepagedata.csv'); foreach ($pages as $count => $rows) { $page = new Page(); $key = $count + 1; foreach ($rows as $col => $val) { if ($val != 'NULL') { $setter = 'set' . ucfirst($col); if (in_array($col, ['translationParent', 'variantParent'])) { $page->{$setter}($this->getReference('page-' . $val)); } elseif (in_array($col, ['dateAdded', 'variantStartDate'])) { $page->{$setter}(new \DateTime($val)); } elseif (in_array($col, ['content', 'variantSettings'])) { $val = unserialize(stripslashes($val)); $page->{$setter}($val); } else { $page->{$setter}($val); } } } $page->setCategory($this->getReference('page-cat-1')); $repo->saveEntity($page); $this->setReference('page-' . $key, $page); } }
/** * Get a count of unique hits for the current tracking ID * * @param Page|Redirect $page * @param string $trackingId * * @return int * @throws \Doctrine\ORM\NoResultException * @throws \Doctrine\ORM\NonUniqueResultException */ public function getHitCountForTrackingId($page, $trackingId) { $q = $this->createQueryBuilder('h')->select('count(h.id) as num'); if ($page instanceof Page) { $q->where('IDENTITY(h.page) = ' . $page->getId()); } elseif ($page instanceof Redirect) { $q->where('IDENTITY(h.redirect) = ' . $page->getId()); } $q->andWhere('h.trackingId = :id')->setParameter('id', $trackingId); $count = $q->getQuery()->getSingleResult(); return (int) $count['num']; }
/** * Determine if the page hit is a unique * * @param Page|Redirect $page * @param string $trackingId * * @return bool */ public function isUniquePageHit($page, $trackingId) { $q = $this->getEntityManager()->getConnection()->createQueryBuilder(); $q2 = $this->getEntityManager()->getConnection()->createQueryBuilder(); $q2->select('null')->from(MAUTIC_TABLE_PREFIX . 'page_hits', 'h'); $expr = $q2->expr()->andX($q2->expr()->eq('h.tracking_id', ':id')); if ($page instanceof Page) { $expr->add($q2->expr()->eq('h.page_id', $page->getId())); } elseif ($page instanceof Redirect) { $expr->add($q2->expr()->eq('h.redirect_id', $page->getId())); } $q2->where($expr); $q->select('u.is_unique')->from(sprintf('(SELECT (NOT EXISTS (%s)) is_unique)', $q2->getSQL()), 'u')->setParameter('id', $trackingId); return (bool) $q->execute()->fetchColumn(); }
/** * @param string $alias * @param Page $entity * * @return mixed */ public function checkUniqueAlias($alias, $entity = null) { $q = $this->createQueryBuilder('e')->select('count(e.id) as alias_count')->where('e.alias = :alias'); $q->setParameter('alias', $alias); if (!empty($entity)) { $parent = $entity->getTranslationParent(); $children = $entity->getTranslationChildren(); if ($parent || count($children)) { //allow same alias among language group $ids = array(); if (!empty($parent)) { $children = $parent->getTranslationChildren(); $ids[] = $parent->getId(); } foreach ($children as $child) { if ($child->getId() != $entity->getId()) { $ids[] = $child->getId(); } } $q->andWhere($q->expr()->notIn('e.id', $ids)); } $parent = $entity->getVariantParent(); $children = $entity->getVariantChildren(); if ($parent || count($children)) { //allow same alias among language group $ids = array(); if (!empty($parent)) { $children = $parent->getVariantChildren(); $ids[] = $parent->getId(); } foreach ($children as $child) { if ($child->getId() != $entity->getId()) { $ids[] = $child->getId(); } } $q->andWhere($q->expr()->notIn('e.id', $ids)); } if ($entity->getId()) { $q->andWhere('e.id != :id'); $q->setParameter('id', $entity->getId()); } } $results = $q->getQuery()->getSingleResult(); return $results['alias_count']; }
/** * PreProcess page slots for public view. * * @deprecated - to be removed in 3.0 * * @param array $slots * @param Page $entity */ private function processSlots($slots, $entity) { /** @var \Mautic\CoreBundle\Templating\Helper\AssetsHelper $assetsHelper */ $assetsHelper = $this->factory->getHelper('template.assets'); /** @var \Mautic\CoreBundle\Templating\Helper\SlotsHelper $slotsHelper */ $slotsHelper = $this->factory->getHelper('template.slots'); $content = $entity->getContent(); foreach ($slots as $slot => $slotConfig) { // backward compatibility - if slotConfig array does not exist if (is_numeric($slot)) { $slot = $slotConfig; $slotConfig = []; } if (isset($slotConfig['type']) && $slotConfig['type'] == 'slideshow') { if (isset($content[$slot])) { $options = json_decode($content[$slot], true); } else { $options = ['width' => '100%', 'height' => '250px', 'background_color' => 'transparent', 'arrow_navigation' => false, 'dot_navigation' => true, 'interval' => 5000, 'pause' => 'hover', 'wrap' => true, 'keyboard' => true]; } // Create sample slides for first time or if all slides were deleted if (empty($options['slides'])) { $options['slides'] = [['order' => 0, 'background-image' => $assetsHelper->getUrl('media/images/mautic_logo_lb200.png'), 'captionheader' => 'Caption 1'], ['order' => 1, 'background-image' => $assetsHelper->getUrl('media/images/mautic_logo_db200.png'), 'captionheader' => 'Caption 2']]; } // Order slides usort($options['slides'], function ($a, $b) { return strcmp($a['order'], $b['order']); }); $options['slot'] = $slot; $options['public'] = true; $renderingEngine = $this->container->get('templating')->getEngine('MauticPageBundle:Page:Slots/slideshow.html.php'); $slotsHelper->set($slot, $renderingEngine->render('MauticPageBundle:Page:Slots/slideshow.html.php', $options)); } elseif (isset($slotConfig['type']) && $slotConfig['type'] == 'textarea') { $value = isset($content[$slot]) ? nl2br($content[$slot]) : ""; $slotsHelper->set($slot, $value); } else { // Fallback for other types like html, text, textarea and all unknown $value = isset($content[$slot]) ? $content[$slot] : ""; $slotsHelper->set($slot, $value); } } $parentVariant = $entity->getVariantParent(); $title = !empty($parentVariant) ? $parentVariant->getTitle() : $entity->getTitle(); $slotsHelper->set('pageTitle', $title); }
/** * Get translation parent/children * * @param Page $page * * @return array */ public function getTranslations(Page $page) { $parent = $page->getTranslationParent(); if (!empty($parent)) { $children = $parent->getTranslationChildren(); } else { $parent = $page; $children = $page->getTranslationChildren(); } if (empty($children)) { $children = false; } return array($parent, $children); }
/** * PreProcess page slots for public view. * * @param array $slots * @param Page $entity */ private function processSlots($slots, $entity) { /** @var \Mautic\CoreBundle\Templating\Helper\AssetsHelper $assetsHelper */ $assetsHelper = $this->factory->getHelper('template.assets'); /** @var \Mautic\CoreBundle\Templating\Helper\SlotsHelper $slotsHelper */ $slotsHelper = $this->factory->getHelper('template.slots'); /** @var \Mautic\CoreBundle\Templating\Helper\TranslatorHelper $translatorHelper */ $translatorHelper = $this->factory->getHelper('template.translator'); $formFactory = $this->get('form.factory'); $slotsHelper->inBuilder(true); $content = $entity->getContent(); foreach ($slots as $slot => $slotConfig) { // backward compatibility - if slotConfig array does not exist if (is_numeric($slot)) { $slot = $slotConfig; $slotConfig = []; } // define default config if does not exist if (!isset($slotConfig['type'])) { $slotConfig['type'] = 'html'; } if (!isset($slotConfig['placeholder'])) { $slotConfig['placeholder'] = 'mautic.page.builder.addcontent'; } $value = isset($content[$slot]) ? $content[$slot] : ''; if ($slotConfig['type'] == 'slideshow') { if (isset($content[$slot])) { $options = json_decode($content[$slot], true); } else { $options = ['width' => '100%', 'height' => '250px', 'background_color' => 'transparent', 'arrow_navigation' => false, 'dot_navigation' => true, 'interval' => 5000, 'pause' => 'hover', 'wrap' => true, 'keyboard' => true]; } // Create sample slides for first time or if all slides were deleted if (empty($options['slides'])) { $options['slides'] = [['order' => 0, 'background-image' => $assetsHelper->getUrl('media/images/mautic_logo_lb200.png'), 'captionheader' => 'Caption 1'], ['order' => 1, 'background-image' => $assetsHelper->getUrl('media/images/mautic_logo_db200.png'), 'captionheader' => 'Caption 2']]; } // Order slides usort($options['slides'], function ($a, $b) { return strcmp($a['order'], $b['order']); }); $options['slot'] = $slot; $options['public'] = false; // create config form $options['configForm'] = $formFactory->createNamedBuilder(null, 'slideshow_config', [], ['data' => $options])->getForm()->createView(); // create slide config forms foreach ($options['slides'] as $key => &$slide) { $slide['key'] = $key; $slide['slot'] = $slot; $slide['form'] = $formFactory->createNamedBuilder(null, 'slideshow_slide_config', [], ['data' => $slide])->getForm()->createView(); } $renderingEngine = $this->container->get('templating'); if (method_exists($renderingEngine, 'getEngine')) { $renderingEngine->getEngine('MauticPageBundle:Page:Slots/slideshow.html.php'); } $slotsHelper->set($slot, $renderingEngine->render('MauticPageBundle:Page:Slots/slideshow.html.php', $options)); } else { $slotsHelper->set($slot, "<div data-slot=\"text\" id=\"slot-{$slot}\">{$value}</div>"); } } //add builder toolbar $slotsHelper->start('builder'); ?> <input type="hidden" id="builder_entity_id" value="<?php echo $entity->getSessionId(); ?> " /> <?php $slotsHelper->stop(); }
/** * Determines the winner of A/B test based on number of asset downloads * * @param MauticFactory $factory * @param Page $parent * @param $children * * @return array */ public static function determineDownloadWinner($factory, $parent, $children) { $repo = $factory->getEntityManager()->getRepository('MauticAssetBundle:Download'); //if this is an email A/B test, then link email to page to form submission //if it is a page A/B test, then link form submission to page $type = $parent instanceof Email ? 'email' : 'page'; $ids = array($parent->getId()); foreach ($children as $c) { if ($c->isPublished()) { $id = $c->getId(); $ids[] = $id; } } $startDate = $parent->getVariantStartDate(); if ($startDate != null && !empty($ids)) { $counts = $type == 'page' ? $repo->getDownloadCountsByPage($ids, $startDate) : $repo->getDownloadCountsByEmail($ids, $startDate); $translator = $factory->getTranslator(); if ($counts) { $downloads = $support = $data = array(); $hasResults = array(); $downloadsLabel = $translator->trans('mautic.asset.abtest.label.downloads'); $hitsLabel = $type == 'page' ? $translator->trans('mautic.asset.abtest.label.hits') : $translator->trans('mautic.asset.abtest.label.sentemils'); foreach ($counts as $stats) { $rate = $stats['total'] ? round($stats['count'] / $stats['total'] * 100, 2) : 0; $downloads[$stats['id']] = $rate; $data[$downloadsLabel][] = $stats['count']; $data[$hitsLabel][] = $stats['total']; $support['labels'][] = $stats['id'] . ':' . $stats['name'] . ' (' . $rate . '%)'; $hasResults[] = $stats['id']; } //make sure that parent and published children are included if (!in_array($parent->getId(), $hasResults)) { $data[$downloadsLabel][] = 0; $data[$hitsLabel][] = 0; $support['labels'][] = $parent->getId() . ':' . ($type == 'page' ? $parent->getTitle() : $parent->getName()) . ' (0%)'; } foreach ($children as $c) { if ($c->isPublished()) { if (!in_array($c->getId(), $hasResults)) { $data[$downloadsLabel][] = 0; $data[$hitsLabel][] = 0; $support['labels'][] = $c->getId() . ':' . ($type == 'page' ? $c->getTitle() : $c->getName()) . ' (0%)'; } } } $support['data'] = $data; //set max for scales $maxes = array(); foreach ($support['data'] as $label => $data) { $maxes[] = max($data); } $top = max($maxes); $support['step_width'] = ceil($top / 10) * 10; //put in order from least to greatest just because asort($downloads); //who's the winner? $max = max($downloads); //get the page ids with the most number of downloads $winners = $max > 0 ? array_keys($downloads, $max) : array(); return array('winners' => $winners, 'support' => $support, 'basedOn' => 'asset.downloads', 'supportTemplate' => 'MauticPageBundle:SubscribedEvents\\AbTest:bargraph.html.php'); } } return array('winners' => array(), 'support' => array(), 'basedOn' => 'asset.downloads'); }
/** * @deprecated 2.1 - use $entity->getVariants() instead; to be removed in 3.0 * * @param Page $entity * * @return array */ public function getVariants(Page $entity) { return $entity->getVariants(); }
/** * {@inheritDoc} */ public function __toString() { $this->__initializer__ && $this->__initializer__->__invoke($this, '__toString', array()); return parent::__toString(); }