PluginProbe
Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification / 5.6.0
Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification v5.6.0
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 3.0.60 3.0.61 3.0.62 3.0.70 3.0.71 3.0.72 All 35 releases
double-opt-in / src / FollowUp / FollowUpStatus.php

FollowUpStatus.php in Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification 5.6.0, at src/FollowUp/FollowUpStatus.php

126 lines 3.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Follow-up action states.
4 *
5 * @package Forge12\DoubleOptIn\FollowUp
6 * @since 5.6.0
7 */
8
9 declare( strict_types=1 );
10
11 namespace Forge12\DoubleOptIn\FollowUp;
12
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit;
15 }
16
17 /**
18 * The lifecycle of one follow-up action (one row in the follow-up table).
19 *
20 * pending ──claim──> running ──> succeeded | skipped
21 * │ ──> failed_retryable ──claim──> running …
22 * │ ──> failed_permanent
23 * └──> unknown (timeout after send, crash, lease expiry)
24 *
25 * `unknown` is deliberately not retried on its own: the action may have
26 * run. Only an administrator who accepts the risk of a duplicate can
27 * push it back into `running`.
28 */
29 final class FollowUpStatus {
30
31 public const PENDING = 'pending';
32 public const RUNNING = 'running';
33 public const SUCCEEDED = 'succeeded';
34 public const FAILED_RETRYABLE = 'failed_retryable';
35 public const FAILED_PERMANENT = 'failed_permanent';
36 public const UNKNOWN = 'unknown';
37 public const SKIPPED = 'skipped';
38
39 /**
40 * Aggregate states for one opt-in (derived, never stored).
41 */
42 public const AGGREGATE_NONE = 'none';
43 public const AGGREGATE_LEGACY_UNKNOWN = 'legacy_unknown';
44 public const AGGREGATE_PENDING = 'pending';
45 public const AGGREGATE_COMPLETED = 'completed';
46 public const AGGREGATE_PARTIAL = 'partial';
47 public const AGGREGATE_FAILED = 'failed';
48 public const AGGREGATE_UNKNOWN = 'unknown';
49
50 /**
51 * @return string[]
52 */
53 public static function all(): array {
54 return array(
55 self::PENDING,
56 self::RUNNING,
57 self::SUCCEEDED,
58 self::FAILED_RETRYABLE,
59 self::FAILED_PERMANENT,
60 self::UNKNOWN,
61 self::SKIPPED,
62 );
63 }
64
65 /**
66 * States from which a result can no longer change without an
67 * explicit administrator decision.
68 */
69 public static function isSettled( string $status ): bool {
70 return in_array( $status, array( self::SUCCEEDED, self::SKIPPED, self::FAILED_PERMANENT, self::UNKNOWN ), true );
71 }
72
73 /**
74 * States counted as "nothing left to do".
75 */
76 public static function isDone( string $status ): bool {
77 return $status === self::SUCCEEDED || $status === self::SKIPPED;
78 }
79
80 /**
81 * States that need attention in the admin list.
82 *
83 * @return string[]
84 */
85 public static function problematic(): array {
86 return array( self::FAILED_RETRYABLE, self::FAILED_PERMANENT, self::UNKNOWN );
87 }
88
89 /**
90 * Derive the aggregate state of one opt-in from its action states.
91 *
92 * @param string[] $statuses One status per action row.
93 */
94 public static function aggregate( array $statuses ): string {
95 if ( empty( $statuses ) ) {
96 return self::AGGREGATE_NONE;
97 }
98
99 $has = array_fill_keys( self::all(), 0 );
100 foreach ( $statuses as $status ) {
101 if ( isset( $has[ $status ] ) ) {
102 $has[ $status ]++;
103 }
104 }
105
106 if ( $has[ self::PENDING ] > 0 || $has[ self::RUNNING ] > 0 ) {
107 return self::AGGREGATE_PENDING;
108 }
109
110 $problems = $has[ self::FAILED_RETRYABLE ] + $has[ self::FAILED_PERMANENT ] + $has[ self::UNKNOWN ];
111 if ( $problems === 0 ) {
112 return self::AGGREGATE_COMPLETED;
113 }
114
115 if ( $has[ self::SUCCEEDED ] > 0 ) {
116 return self::AGGREGATE_PARTIAL;
117 }
118
119 if ( $has[ self::FAILED_RETRYABLE ] + $has[ self::FAILED_PERMANENT ] === 0 ) {
120 return self::AGGREGATE_UNKNOWN;
121 }
122
123 return self::AGGREGATE_FAILED;
124 }
125 }
126