PluginProbe
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz / 2.12.8
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz v2.12.8
2.12.8 2.12.7 2.12.6 2.12.5 2.12.4 2.12.3 2.12.2 2.12.1 2.12.0 2.11.1 2.11.0 2.10.1 2.10.0 2.9.1 2.9.0 2.8.2 2.8.1 2.7.0 2.7.1 2.8.0 trunk 0.0.10 0.0.11 0.0.12 0.0.13 All 98 releases
← All changes | inc/lib/bsf-analytics/class-bsf-analytics-events.php +49 -12 2.7.0 → 2.12.8 View file →
@@ -57,44 +57,81 @@
57 57 );
58 58 }
59 59
60 60 /**
61 - * Track a one-time event. Skips if already tracked or pending.
61 + * Track an event. By default, skips if already tracked or pending (one-time semantics).
62 + * When $force is true, the event is treated as retrackable — bypasses the post-send
63 + * dedup check and overwrites any pending entry with the same name. Useful for
64 + * recurring events like `plugin_updated` where the latest value should always win.
62 65 * Only stores temporary data — cleaned up after analytics send.
63 66 *
64 67 * @param string $event_name Event identifier.
65 68 * @param string $event_value Primary value (version, form ID, mode, etc.).
66 - * @param array<string, mixed> $properties Additional context as key-value pairs.
69 + * @param array<string, mixed> $properties Additional context as key-value pairs. Values are stored as-is — sanitization is the caller's responsibility.
70 + * @param bool $force When true, bypass pushed dedup and overwrite pending entry. Default false.
67 71 * @since 1.1.21
72 + * @since 1.1.25 Added the $force parameter.
68 73 * @return void
69 74 */
70 - public function track( $event_name, $event_value = '', $properties = array() ) {
75 + public function track( $event_name, $event_value = '', $properties = array(), $force = false ) {
71 76 // Sanitize inputs once upfront — ensures dedup comparisons match stored values.
72 77 $event_name = sanitize_text_field( $event_name );
73 78 $event_value = sanitize_text_field( (string) $event_value );
74 79 $properties = is_array( $properties ) ? $properties : array();
80 + $force = (bool) $force;
75 81
76 82 // Check dedup flag — already sent in a previous cycle.
77 - $pushed = $this->get_option( 'usage_events_pushed', array() );
78 - $pushed = is_array( $pushed ) ? $pushed : array();
79 - if ( in_array( $event_name, $pushed, true ) ) {
80 - return;
83 + // Force bypasses this check; pushed list will be refreshed on next flush_pending().
84 + if ( ! $force ) {
85 + $pushed = $this->get_option( 'usage_events_pushed', array() );
86 + $pushed = is_array( $pushed ) ? $pushed : array();
87 + if ( in_array( $event_name, $pushed, true ) ) {
88 + return;
89 + }
81 90 }
82 91
83 92 // Check if already queued in current cycle.
84 93 $pending = $this->get_option( 'usage_events_pending', array() );
85 94 $pending = is_array( $pending ) ? $pending : array();
86 - if ( in_array( $event_name, array_column( $pending, 'event_name' ), true ) ) {
87 - return;
88 - }
89 95
90 - // Add to pending queue.
91 - $pending[] = array(
96 + $new_event = array(
92 97 'event_name' => $event_name,
93 98 'event_value' => $event_value,
94 99 'properties' => $properties,
95 100 'date' => current_time( 'mysql' ),
96 101 );
102 +
103 + if ( ! $force ) {
104 + // Default path: cheap membership check — no need to locate the key.
105 + if ( in_array( $event_name, array_column( $pending, 'event_name' ), true ) ) {
106 + return;
107 + }
108 + $pending[] = $new_event;
109 + } else {
110 + // Force path: locate any existing entry by actual key to overwrite safely.
111 + $existing_key = null;
112 + foreach ( $pending as $key => $entry ) {
113 + if ( isset( $entry['event_name'] ) && $entry['event_name'] === $event_name ) {
114 + $existing_key = $key;
115 + break;
116 + }
117 + }
118 +
119 + if ( null !== $existing_key ) {
120 + // Skip the write when nothing material changed (only `date` would differ).
121 + $existing = $pending[ $existing_key ];
122 + if ( array_key_exists( 'event_value', $existing )
123 + && array_key_exists( 'properties', $existing )
124 + && $existing['event_value'] === $new_event['event_value']
125 + && $existing['properties'] === $new_event['properties'] ) {
126 + return;
127 + }
128 + $pending[ $existing_key ] = $new_event;
129 + } else {
130 + $pending[] = $new_event;
131 + }
132 + }
133 +
97 134 $this->update_option( 'usage_events_pending', $pending );
98 135 }
99 136
100 137 /**