44
55namespace PhpList \Core \Domain \Analytics \Service ;
66
7+ use DateTimeImmutable ;
8+ use PhpList \Core \Domain \Analytics \Repository \UserMessageViewRepository ;
79use PhpList \Core \Domain \Analytics \Service \Manager \LinkTrackManager ;
810use PhpList \Core \Domain \Analytics \Service \Manager \UserMessageViewManager ;
911use PhpList \Core \Domain \Messaging \Repository \MessageRepository ;
1012use PhpList \Core \Domain \Messaging \Repository \UserMessageBounceRepository ;
1113use PhpList \Core \Domain \Messaging \Repository \UserMessageForwardRepository ;
14+ use PhpList \Core \Domain \Messaging \Repository \UserMessageRepository ;
1215use PhpList \Core \Domain \Subscription \Repository \SubscriberRepository ;
1316
1417class AnalyticsService
@@ -19,7 +22,9 @@ public function __construct(
1922 private readonly MessageRepository $ messageRepository ,
2023 private readonly UserMessageBounceRepository $ messageBounceRepository ,
2124 private readonly UserMessageForwardRepository $ messageForwardRepository ,
22- private readonly SubscriberRepository $ subscriberRepository
25+ private readonly SubscriberRepository $ subscriberRepository ,
26+ private readonly UserMessageRepository $ userMessageRepository ,
27+ private readonly UserMessageViewRepository $ userMessageViewRepository
2328 ) {
2429 }
2530
@@ -180,6 +185,86 @@ public function getTopDomains(int $limit = 50, int $minSubscribers = 5): array
180185 ];
181186 }
182187
188+ public function getSummaryStatistics (): array
189+ {
190+ $ now = new DateTimeImmutable ();
191+ $ thisMonthStart = $ now ->modify ('first day of this month 00:00:00 ' );
192+ $ lastMonthStart = $ now ->modify ('first day of last month 00:00:00 ' );
193+ $ lastMonthEnd = $ thisMonthStart ->modify ('-1 second ' );
194+
195+ $ totalSubscribers = $ this ->subscriberRepository ->count ([]);
196+ $ subscribersThisMonth = $ this ->subscriberRepository ->countCreatedBetween ($ thisMonthStart , $ now );
197+ $ subscribersLastMonth = $ this ->subscriberRepository ->countCreatedBetween ($ lastMonthStart , $ lastMonthEnd );
198+
199+ $ activeCampaigns = $ this ->messageRepository ->countActiveBetween ($ thisMonthStart , $ now );
200+ $ activeCampaignsLastMonth = $ this ->messageRepository ->countActiveBetween ($ lastMonthStart , $ lastMonthEnd );
201+
202+ $ sentTotal = $ this ->userMessageRepository ->countSentBetween ($ thisMonthStart , $ now );
203+ $ openTotal = $ this ->userMessageViewRepository ->countBetween ($ thisMonthStart , $ now );
204+ $ bounceTotal = $ this ->messageBounceRepository ->countBetween ($ thisMonthStart , $ now );
205+
206+ $ sentTotalLastMonth = $ this ->userMessageRepository ->countSentBetween ($ lastMonthStart , $ lastMonthEnd );
207+ $ openTotalLastMonth = $ this ->userMessageViewRepository ->countBetween ($ lastMonthStart , $ lastMonthEnd );
208+ $ bounceTotalLastMonth = $ this ->messageBounceRepository ->countBetween ($ lastMonthStart , $ lastMonthEnd );
209+
210+ $ openRate = $ this ->calculateRate ($ openTotal , $ sentTotal );
211+ $ openRateLastMonth = $ this ->calculateRate ($ openTotalLastMonth , $ sentTotalLastMonth );
212+
213+ $ bounceRate = $ this ->calculateRate ($ bounceTotal , $ sentTotal );
214+ $ bounceRateLastMonth = $ this ->calculateRate ($ bounceTotalLastMonth , $ sentTotalLastMonth );
215+
216+ return [
217+ 'total_subscribers ' => [
218+ 'value ' => $ totalSubscribers ,
219+ 'change_vs_last_month ' => $ this ->calculateChange ($ subscribersThisMonth , $ subscribersLastMonth ),
220+ ],
221+ 'active_campaigns ' => [
222+ 'value ' => $ activeCampaigns ,
223+ 'change_vs_last_month ' => $ this ->calculateChange ($ activeCampaigns , $ activeCampaignsLastMonth ),
224+ ],
225+ 'open_rate ' => [
226+ 'value ' => $ openRate ,
227+ 'change_vs_last_month ' => $ this ->calculateChange ($ openRate , $ openRateLastMonth ),
228+ ],
229+ 'bounce_rate ' => [
230+ 'value ' => $ bounceRate ,
231+ 'change_vs_last_month ' => $ this ->calculateChange ($ bounceRate , $ bounceRateLastMonth ),
232+ ],
233+ ];
234+ }
235+
236+ /**
237+ * Calculate rate as a percentage.
238+ *
239+ * @param int $numerator
240+ * @param int $denominator
241+ * @return float
242+ */
243+ private function calculateRate (int $ numerator , int $ denominator ): float
244+ {
245+ if ($ denominator === 0 ) {
246+ return 0.0 ;
247+ }
248+
249+ return round (($ numerator / $ denominator ) * 100 , 2 );
250+ }
251+
252+ /**
253+ * Calculate percentage change between current and previous value.
254+ *
255+ * @param float|int $current
256+ * @param float|int $previous
257+ * @return float
258+ */
259+ private function calculateChange (float |int $ current , float |int $ previous ): float
260+ {
261+ if ($ previous == 0 ) {
262+ return $ current > 0 ? 100.0 : 0.0 ;
263+ }
264+
265+ return round ((($ current - $ previous ) / $ previous ) * 100 , 2 );
266+ }
267+
183268 /**
184269 * Get domains with most unconfirmed subscribers
185270 *
0 commit comments