Issues (3627)

EventListener/DetermineWinnerSubscriber.php (1 issue)

1
<?php
2
3
/*
4
 * @copyright   2019 Mautic Contributors. All rights reserved
5
 * @author      Mautic
6
 *
7
 * @link        http://mautic.org
8
 *
9
 * @license     GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
10
 */
11
12
namespace Mautic\PageBundle\EventListener;
13
14
use Mautic\CoreBundle\Event\DetermineWinnerEvent;
15
use Mautic\PageBundle\Entity\HitRepository;
16
use Mautic\PageBundle\PageEvents;
17
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
18
use Symfony\Component\Translation\TranslatorInterface;
19
20
class DetermineWinnerSubscriber implements EventSubscriberInterface
21
{
22
    /**
23
     * @var HitRepository
24
     */
25
    private $hitRepository;
26
27
    /**
28
     * @var TranslatorInterface
29
     */
30
    private $translator;
31
32
    public function __construct(HitRepository $hitRepository, TranslatorInterface $translator)
33
    {
34
        $this->hitRepository = $hitRepository;
35
        $this->translator    = $translator;
36
    }
37
38
    /**
39
     * @return array
40
     */
41
    public static function getSubscribedEvents()
42
    {
43
        return [
44
            PageEvents::ON_DETERMINE_BOUNCE_RATE_WINNER => ['onDetermineBounceRateWinner', 0],
45
            PageEvents::ON_DETERMINE_DWELL_TIME_WINNER  => ['onDetermineDwellTimeWinner', 0],
46
        ];
47
    }
48
49
    /**
50
     * Determines the winner of A/B test based on bounce rates.
51
     */
52
    public function onDetermineBounceRateWinner(DetermineWinnerEvent $event)
53
    {
54
        //find the hits that did not go any further
55
        $parent    = $event->getParameters()['parent'];
56
        $children  = $event->getParameters()['children'];
57
        $pageIds   = $parent->getRelatedEntityIds();
58
        $startDate = $parent->getVariantStartDate();
59
60
        if (null != $startDate && !empty($pageIds)) {
61
            //get their bounce rates
62
            $counts = $this->hitRepository->getBounces($pageIds, $startDate, true);
63
            if ($counts) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $counts of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
64
                // Group by translation
65
                $combined = [
66
                    $parent->getId() => $counts[$parent->getId()],
67
                ];
68
69
                if ($parent->hasTranslations()) {
70
                    $translations = $parent->getTranslationChildren()->getKeys();
71
72
                    foreach ($translations as $translation) {
73
                        $combined[$parent->getId()]['bounces'] += $counts[$translation]['bounces'];
74
                        $combined[$parent->getId()]['totalHits'] += $counts[$translation]['totalHits'];
75
                        $combined[$parent->getId()]['rate'] = ($combined[$parent->getId()]['totalHits']) ? round(
76
                            ($combined[$parent->getId()]['bounces'] / $combined[$parent->getId()]['totalHits']) * 100,
77
                            2
78
                        ) : 0;
79
                    }
80
                }
81
82
                foreach ($children as $child) {
83
                    $combined[$child->getId()] = $counts[$child->getId()];
84
85
                    if ($child->hasTranslations()) {
86
                        $translations              = $child->getTranslationChildren()->getKeys();
87
                        foreach ($translations as $translation) {
88
                            $combined[$child->getId()]['bounces'] += $counts[$translation]['bounces'];
89
                            $combined[$child->getId()]['totalHits'] += $counts[$translation]['totalHits'];
90
                            $combined[$child->getId()]['rate'] = ($combined[$child->getId()]['totalHits']) ? round(
91
                                ($combined[$child->getId()]['bounces'] / $combined[$child->getId()]['totalHits']) * 100,
92
                                2
93
                            ) : 0;
94
                        }
95
                    }
96
                }
97
                unset($counts);
98
99
                //let's arrange by rate
100
                $rates             = [];
101
                $support['data']   = [];
102
                $support['labels'] = [];
103
                $bounceLabel       = $this->translator->trans('mautic.page.abtest.label.bounces');
104
105
                foreach ($combined as $pid => $stats) {
106
                    $rates[$pid]                     = $stats['rate'];
107
                    $support['data'][$bounceLabel][] = $rates[$pid];
108
                    $support['labels'][]             = $pid.':'.$stats['title'];
109
                }
110
111
                // investigate the rate calculation, seems that lowest value should be the winner
112
                $max                   = max($rates);
113
                $support['step_width'] = (ceil($max / 10) * 10);
114
115
                $winners = ($max > 0) ? array_keys($rates, $max) : [];
116
117
                $event->setAbTestResults([
118
                    'winners'         => $winners,
119
                    'support'         => $support,
120
                    'basedOn'         => 'page.bouncerate',
121
                    'supportTemplate' => 'MauticPageBundle:SubscribedEvents\AbTest:bargraph.html.php',
122
                ]);
123
124
                return;
125
            }
126
        }
127
128
        $event->setAbTestResults([
129
            'winners' => [],
130
            'support' => [],
131
            'basedOn' => 'page.bouncerate',
132
        ]);
133
    }
134
135
    /**
136
     * Determines the winner of A/B test based on dwell time rates.
137
     */
138
    public function onDetermineDwellTimeWinner(DetermineWinnerEvent $event)
139
    {
140
        //find the hits that did not go any further
141
        $parent    = $event->getParameters()['parent'];
142
        $pageIds   = $parent->getRelatedEntityIds();
143
        $startDate = $parent->getVariantStartDate();
144
145
        if (null != $startDate && !empty($pageIds)) {
146
            //get their bounce rates
147
            $counts  = $this->hitRepository->getDwellTimesForPages($pageIds, ['fromDate' => $startDate]);
148
            $support = [];
149
150
            if ($counts) {
151
                //in order to get a fair grade, we have to compare the averages here since a page that is only shown
152
                //25% of the time will have a significantly lower sum than a page shown 75% of the time
153
                $avgs              = [];
154
                $support['data']   = [];
155
                $support['labels'] = [];
156
                foreach ($counts as $pid => $stats) {
157
                    $avgs[$pid]                                                                                = $stats['average'];
158
                    $support['data'][$this->translator->trans('mautic.page.abtest.label.dewlltime.average')][] = $stats['average'];
159
                    $support['labels'][]                                                                       = $pid.':'.$stats['title'];
160
                }
161
162
                //set max for scales
163
                $max                   = max($avgs);
164
                $support['step_width'] = (ceil($max / 10) * 10);
165
166
                //get the page ids with the greatest average dwell time
167
                $winners = ($max > 0) ? array_keys($avgs, $max) : [];
168
169
                $event->setAbTestResults([
170
                    'winners'         => $winners,
171
                    'support'         => $support,
172
                    'basedOn'         => 'page.dwelltime',
173
                    'supportTemplate' => 'MauticPageBundle:SubscribedEvents\AbTest:bargraph.html.php',
174
                ]);
175
176
                return;
177
            }
178
        }
179
180
        $event->setAbTestResults([
181
            'winners' => [],
182
            'support' => [],
183
            'basedOn' => 'page.dwelltime',
184
        ]);
185
    }
186
}
187