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
|
|||
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 |
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.