PluginProbe
Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification / 5.8.1
Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification v5.8.1
5.8.0 5.8.1 5.7.0 5.6.2 5.6.3 5.6.1 5.6.0 5.5.0 5.4.0 5.3.2 5.3.1 5.1.6 5.1.5 trunk 2.1.5 2.11 2.12 2.13 2.15 3.0.0 3.0.1 3.0.2 3.0.3 3.0.5 3.0.51 All 41 releases
double-opt-in / src / Service / StuckOptInsReport.php

StuckOptInsReport.php in Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification 5.8.1, at src/Service/StuckOptInsReport.php

92 lines 2.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * "Many of your opt-ins are not confirmed" — the numbers behind the
4 * dashboard card.
5 *
6 * Looks at the last 30 days minus the last 24 hours (those can still be
7 * confirmed) and speaks up only when there is enough data and a real
8 * share is stuck. Also counts the confirmation mails that failed in the
9 * same period, which is the first thing to fix.
10 *
11 * @package Forge12\DoubleOptIn\Service
12 * @since 5.8.0
13 */
14
15 declare( strict_types=1 );
16
17 namespace Forge12\DoubleOptIn\Service;
18
19 use Forge12\DoubleOptIn\Repository\OptInMailStatusRepository;
20 use Forge12\DoubleOptIn\Repository\OptInStatsRepository;
21
22 if ( ! defined( 'ABSPATH' ) ) {
23 exit;
24 }
25
26 class StuckOptInsReport {
27
28 public const WINDOW_DAYS = 30;
29
30 public const GRACE_SECONDS = 86400;
31
32 public const MIN_OPTINS = 10;
33
34 public const MIN_SHARE = 30;
35
36 /** @var OptInStatsRepository */
37 private $stats;
38
39 /** @var OptInMailStatusRepository */
40 private $mailStatus;
41
42 /** @var callable(): int */
43 private $clock;
44
45 public function __construct( OptInStatsRepository $stats, OptInMailStatusRepository $mailStatus, ?callable $clock = null ) {
46 $this->stats = $stats;
47 $this->mailStatus = $mailStatus;
48 $this->clock = $clock ?? 'time';
49 }
50
51 /**
52 * The report, or null when there is nothing worth saying.
53 *
54 * @return array{days: int, total: int, unconfirmed: int, share: int, mailFailed: int}|null
55 */
56 public function report(): ?array {
57 $now = (int) call_user_func( $this->clock );
58 $window = $this->stats->confirmationWindow( $now - self::WINDOW_DAYS * 86400, $now - self::GRACE_SECONDS );
59
60 if ( $window['total'] < self::MIN_OPTINS ) {
61 return null;
62 }
63
64 $share = (int) round( $window['unconfirmed'] * 100 / $window['total'] );
65 if ( $share < self::MIN_SHARE ) {
66 return null;
67 }
68
69 return array(
70 'days' => self::WINDOW_DAYS,
71 'total' => $window['total'],
72 'unconfirmed' => $window['unconfirmed'],
73 'share' => $share,
74 'mailFailed' => $this->mailStatus->countFailedSince( self::WINDOW_DAYS * 86400 ),
75 );
76 }
77
78 /**
79 * `f12_doi_rest_dashboard_stats`: add `stuckOptins`.
80 *
81 * @param mixed $data Dashboard payload.
82 *
83 * @return mixed
84 */
85 public function addToDashboard( $data ) {
86 if ( is_array( $data ) ) {
87 $data['stuckOptins'] = $this->report();
88 }
89 return $data;
90 }
91 }
92