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\EmailBundle\EventListener;
13
14
use Doctrine\ORM\EntityManager;
15
use Mautic\CoreBundle\Event\DetermineWinnerEvent;
16
use Mautic\EmailBundle\EmailEvents;
17
use Mautic\EmailBundle\Entity\Email;
18
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
19
use Symfony\Component\Translation\TranslatorInterface;
20
21
class DetermineWinnerSubscriber implements EventSubscriberInterface
22
{
23
    /**
24
     * @var EntityManager
25
     */
26
    private $em;
27
28
    /**
29
     * @var TranslatorInterface
30
     */
31
    private $translator;
32
33
    public function __construct(EntityManager $em, TranslatorInterface $translator)
34
    {
35
        $this->em         = $em;
36
        $this->translator = $translator;
37
    }
38
39
    /**
40
     * @return array
41
     */
42
    public static function getSubscribedEvents()
43
    {
44
        return [
45
            EmailEvents::ON_DETERMINE_OPEN_RATE_WINNER         => ['onDetermineOpenRateWinner', 0],
46
            EmailEvents::ON_DETERMINE_CLICKTHROUGH_RATE_WINNER => ['onDetermineClickthroughRateWinner', 0],
47
        ];
48
    }
49
50
    /**
51
     * Determines the winner of A/B test based on open rate.
52
     */
53
    public function onDetermineOpenRateWinner(DetermineWinnerEvent $event)
54
    {
55
        $parameters = $event->getParameters();
56
        $parent     = $parameters['parent'];
57
        $children   = $parameters['children'];
58
59
        /** @var \Mautic\EmailBundle\Entity\StatRepository $repo */
60
        $repo = $this->em->getRepository('MauticEmailBundle:Stat');
61
        /** @var Email $parent */
62
        $ids       = $parent->getRelatedEntityIds();
63
        $startDate = $parent->getVariantStartDate();
64
65
        if (null != $startDate && !empty($ids)) {
66
            //get their bounce rates
67
            $counts = $repo->getOpenedRates($ids, $startDate);
68
69
            $translator = $this->translator;
70
71
            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...
72
                $rates      = $support      = $data      = [];
73
                $hasResults = [];
74
75
                $parentId = $parent->getId();
76
                foreach ($counts as $id => $stats) {
77
                    if ($id !== $parentId && !array_key_exists($id, $children)) {
78
                        continue;
79
                    }
80
                    $name = ($parentId === $id) ? $parent->getName()
81
                        : $children[$id]->getName();
82
                    $support['labels'][]                                            = $name.' ('.$stats['readRate'].'%)';
83
                    $rates[$id]                                                     = $stats['readRate'];
84
                    $data[$translator->trans('mautic.email.abtest.label.opened')][] = $stats['readCount'];
85
                    $data[$translator->trans('mautic.email.abtest.label.sent')][]   = $stats['totalCount'];
86
                    $hasResults[]                                                   = $id;
87
                }
88
89
                if (!in_array($parent->getId(), $hasResults)) {
90
                    //make sure that parent and published children are included
91
                    $support['labels'][] = $parent->getName().' (0%)';
92
93
                    $data[$translator->trans('mautic.email.abtest.label.opened')][] = 0;
94
                    $data[$translator->trans('mautic.email.abtest.label.sent')][]   = 0;
95
                }
96
97
                foreach ($children as $c) {
98
                    if ($c->isPublished()) {
99
                        if (!in_array($c->getId(), $hasResults)) {
100
                            //make sure that parent and published children are included
101
                            $support['labels'][]                                            = $c->getName().' (0%)';
102
                            $data[$translator->trans('mautic.email.abtest.label.opened')][] = 0;
103
                            $data[$translator->trans('mautic.email.abtest.label.sent')][]   = 0;
104
                        }
105
                    }
106
                }
107
                $support['data'] = $data;
108
109
                //set max for scales
110
                $maxes = [];
111
                foreach ($support['data'] as $data) {
112
                    $maxes[] = max($data);
113
                }
114
                $top                   = max($maxes);
115
                $support['step_width'] = (ceil($top / 10) * 10);
116
117
                //put in order from least to greatest just because
118
                asort($rates);
119
120
                //who's the winner?
121
                $max = max($rates);
122
123
                //get the page ids with the most number of downloads
124
                $winners = ($max > 0) ? array_keys($rates, $max) : [];
125
126
                $event->setAbTestResults([
127
                    'winners'         => $winners,
128
                    'support'         => $support,
129
                    'basedOn'         => 'email.openrate',
130
                    'supportTemplate' => 'MauticPageBundle:SubscribedEvents\AbTest:bargraph.html.php',
131
                ]);
132
133
                return;
134
            }
135
        }
136
137
        $event->setAbTestResults([
138
            'winners' => [],
139
            'support' => [],
140
            'basedOn' => 'email.openrate',
141
        ]);
142
    }
143
144
    /**
145
     * Determines the winner of A/B test based on clickthrough rates.
146
     */
147
    public function onDetermineClickthroughRateWinner(DetermineWinnerEvent $event)
148
    {
149
        $parameters = $event->getParameters();
150
        $parent     = $parameters['parent'];
151
        $children   = $parameters['children'];
152
153
        /** @var \Mautic\PageBundle\Entity\HitRepository $pageRepo */
154
        $pageRepo = $this->em->getRepository('MauticPageBundle:Hit');
155
        /** @var \Mautic\EmailBundle\Entity\StatRepository $emailRepo */
156
        $emailRepo = $this->em->getRepository('MauticEmailBundle:Stat');
157
        /** @var Email $parent */
158
        $ids = $parent->getRelatedEntityIds();
159
160
        $startDate = $parent->getVariantStartDate();
161
        if (null != $startDate && !empty($ids)) {
162
            //get their bounce rates
163
            $clickthroughCounts = $pageRepo->getEmailClickthroughHitCount($ids, $startDate);
164
            $sentCounts         = $emailRepo->getSentCounts($ids, $startDate);
165
166
            $translator = $this->translator;
167
            if ($clickthroughCounts) {
168
                $rates      = $support      = $data      = [];
169
                $hasResults = [];
170
171
                $parentId = $parent->getId();
172
                foreach ($clickthroughCounts as $id => $count) {
173
                    if ($id !== $parentId && !array_key_exists($id, $children)) {
174
                        continue;
175
                    }
176
                    if (!isset($sentCounts[$id])) {
177
                        $sentCounts[$id] = 0;
178
                    }
179
180
                    $rates[$id] = $sentCounts[$id] ? round(($count / $sentCounts[$id]) * 100, 2) : 0;
181
182
                    $name                = ($parentId === $id) ? $parent->getName() : $children[$id]->getName();
183
                    $support['labels'][] = $name.' ('.$rates[$id].'%)';
184
185
                    $data[$translator->trans('mautic.email.abtest.label.clickthrough')][]     = $count;
186
                    $data[$translator->trans('mautic.email.abtest.label.opened')][]           = $sentCounts[$id];
187
                    $hasResults[]                                                             = $id;
188
                }
189
190
                if (!in_array($parent->getId(), $hasResults)) {
191
                    //make sure that parent and published children are included
192
                    $support['labels'][] = $parent->getName().' (0%)';
193
194
                    $data[$translator->trans('mautic.email.abtest.label.clickthrough')][] = 0;
195
                    $data[$translator->trans('mautic.email.abtest.label.opened')][]       = 0;
196
                }
197
198
                foreach ($children as $c) {
199
                    if ($c->isPublished()) {
200
                        if (!in_array($c->getId(), $hasResults)) {
201
                            //make sure that parent and published children are included
202
                            $support['labels'][]                                                  = $c->getName().' (0%)';
203
                            $data[$translator->trans('mautic.email.abtest.label.clickthrough')][] = 0;
204
                            $data[$translator->trans('mautic.email.abtest.label.opened')][]       = 0;
205
                        }
206
                    }
207
                }
208
                $support['data'] = $data;
209
210
                //set max for scales
211
                $maxes = [];
212
                foreach ($support['data'] as $data) {
213
                    $maxes[] = max($data);
214
                }
215
                $top                   = max($maxes);
216
                $support['step_width'] = (ceil($top / 10) * 10);
217
218
                //put in order from least to greatest just because
219
                asort($rates);
220
221
                //who's the winner?
222
                $max = max($rates);
223
224
                //get the page ids with the most number of downloads
225
                $winners = ($max > 0) ? array_keys($rates, $max) : [];
226
227
                $event->setAbTestResults([
228
                    'winners'         => $winners,
229
                    'support'         => $support,
230
                    'basedOn'         => 'email.clickthrough',
231
                    'supportTemplate' => 'MauticPageBundle:SubscribedEvents\AbTest:bargraph.html.php',
232
                ]);
233
234
                return;
235
            }
236
        }
237
238
        $event->setAbTestResults([
239
            'winners' => [],
240
            'support' => [],
241
            'basedOn' => 'email.clickthrough',
242
        ]);
243
    }
244
}
245