PluginProbe ʕ •ᴥ•ʔ
Smash Balloon Social Post Feed – Simple Social Feeds for WordPress / 4.10.0
Smash Balloon Social Post Feed – Simple Social Feeds for WordPress v4.10.0
4.12.0 4.10.0 4.9.0 4.8.1 trunk 1.0 1.1 1.12.1 1.2.3 1.2.4 1.2.5 1.2.7 1.2.8 1.2.9 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.5 1.5.1 1.5.2 1.5.9 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.4.1 1.6.5 1.6.5.1 1.6.6 1.6.6.1 1.6.6.2 1.6.6.3 1.6.7 1.6.7.1 1.6.8 1.6.8.1 1.6.8.2 1.7.0 1.7.1 1.7.2 1.8.0 1.8.1 1.8.2 1.8.2.1 1.8.2.2 1.8.2.3 1.9.0 1.9.1 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.8.1 1.9.9 1.9.9.1 1.9.9.2 1.9.9.3 2.0 2.0.1 2.1 2.1.1 2.1.2 2.1.3 2.10 2.11 2.11.1 2.12 2.12.1 2.12.2 2.12.3 2.12.4 2.13 2.14 2.14.1 2.15 2.15.1 2.16 2.16.1 2.17 2.17.1 2.18 2.18.1 2.18.2 2.18.3 2.19 2.19.1 2.19.2 2.19.3 2.2 2.2.1 2.3 2.3.1 2.3.10 2.3.2 2.3.3 2.3.4 2.3.6 2.3.7 2.3.8 2.3.9 2.4 2.4.1 2.4.1.1 2.4.1.2 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.5 2.5.1 2.5.2 2.6 2.6.1 2.6.2 2.6.3 2.6.4 2.7 2.7.1 2.7.2 2.8 2.9 2.9.1 4.0 4.0.1 4.0.2 4.0.3 4.0.4 4.0.5 4.1 4.1.1 4.1.2 4.1.3 4.1.4 4.1.5 4.1.6 4.1.7 4.1.8 4.1.9 4.2 4.2.1 4.2.2 4.2.3 4.2.4 4.2.5 4.2.6 4.3.0 4.3.1 4.3.2 4.3.3 4.3.4 4.7.5 4.7.6 4.7.7
custom-facebook-feed / inc / UsageTracking / SmashUsageTracking.php
custom-facebook-feed / inc / UsageTracking Last commit date
Core 3 weeks ago Facebook 3 weeks ago Config.php 3 weeks ago EventRecorder.php 3 weeks ago ReporterInterface.php 3 weeks ago SmashUsageTracking.php 3 weeks ago
SmashUsageTracking.php
240 lines
1 <?php
2 /**
3 * Orchestrates Smash Usage Tracking: schedule, ensure site token, build payload, send.
4 *
5 * @package CustomFacebookFeed\UsageTracking
6 * @since 4.0
7 */
8
9 namespace CustomFacebookFeed\UsageTracking;
10
11 use CustomFacebookFeed\UsageTracking\Core\RegisterSite;
12 use CustomFacebookFeed\UsageTracking\Core\Sender;
13 use CustomFacebookFeed\UsageTracking\Core\PayloadBuilder;
14 use CustomFacebookFeed\UsageTracking\Core\Scheduler;
15 use CustomFacebookFeed\UsageTracking\Facebook\FacebookFreeReporter;
16
17 if ( ! defined( 'ABSPATH' ) ) {
18 exit;
19 }
20
21 class SmashUsageTracking {
22
23 /** @var ReporterInterface */
24 private $reporter;
25
26 /** @var RegisterSite */
27 private $register_site;
28
29 /** @var Sender */
30 private $sender;
31
32 /** @var PayloadBuilder */
33 private $payload_builder;
34
35 /** @var Scheduler */
36 private $scheduler;
37
38 public function __construct() {
39 $this->reporter = new FacebookFreeReporter();
40 $this->register_site = new Core\RegisterSite();
41 $this->sender = new Core\Sender();
42 $this->payload_builder = new Core\PayloadBuilder( $this->reporter );
43 $this->scheduler = new Core\Scheduler();
44
45 add_action( 'init', array( $this, 'maybe_schedule' ) );
46 add_filter( 'cron_schedules', array( $this->scheduler, 'add_schedules' ) );
47 add_action( Config::CRON_HOOK, array( $this, 'send_checkin' ) );
48
49 add_action( 'current_screen', array( $this, 'maybe_record_active_day' ) );
50 add_action( 'wp_ajax_cff_smash_usage_record_event', array( $this, 'ajax_record_event' ) );
51 add_action( 'wp_ajax_cff_smash_usage_record_session', array( $this, 'ajax_record_session' ) );
52 add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_session_script' ), 20 );
53 }
54
55 /**
56 * Schedule cron if enabled and not already scheduled.
57 */
58 public function maybe_schedule() {
59 $this->scheduler->schedule();
60 }
61
62 /**
63 * Cron callback: ensure site token, build payload, send, update last_send.
64 */
65 public function send_checkin() {
66 if ( ! Config::is_enabled() ) {
67 return;
68 }
69
70 $host = wp_parse_url( home_url(), PHP_URL_HOST );
71 if ( 'smashballoon.com' === $host || '.smashballoon.com' === substr( (string) $host, -17 ) ) {
72 return;
73 }
74
75 $opt = get_option( Config::OPTION_TRACKING, array() );
76 $last_send = is_array( $opt ) && isset( $opt['last_send'] ) ? (int) $opt['last_send'] : 0;
77 if ( $last_send > strtotime( '-1 week' ) ) {
78 return;
79 }
80
81 $site_token = get_option( Config::OPTION_SITE_TOKEN, '' );
82 if ( '' === $site_token || ! is_string( $site_token ) ) {
83 $site_token = $this->register_site->register( $this->reporter );
84 if ( null === $site_token ) {
85 return;
86 }
87 }
88
89 $period_end = gmdate( 'Y-m-d', time() - DAY_IN_SECONDS );
90 $period_start = gmdate( 'Y-m-d', time() - 7 * DAY_IN_SECONDS );
91
92 $payload = $this->payload_builder->build( $site_token, $period_start, $period_end );
93 $success = $this->sender->send( $payload );
94
95 if ( $success ) {
96 update_option(
97 Config::OPTION_TRACKING,
98 array(
99 'enabled' => Config::is_enabled(),
100 'last_send' => time(),
101 ),
102 false
103 );
104 $sent_events = isset( $payload['dynamic_metrics']['events'] ) && is_array( $payload['dynamic_metrics']['events'] )
105 ? $payload['dynamic_metrics']['events']
106 : array();
107 $this->reset_events_after_send( $sent_events );
108 }
109 }
110
111 /**
112 * Remove only the event keys that were included in the sent payload.
113 * Events recorded by concurrent AJAX requests after the payload was built
114 * are left intact so they roll over into the next reporting period.
115 *
116 * @param array $sent_events Events map from the sent payload.
117 */
118 private function reset_events_after_send( array $sent_events ) {
119 if ( ! empty( $sent_events ) ) {
120 $stored = get_option( EventRecorder::OPTION_NAME, array() );
121 if ( is_array( $stored ) ) {
122 foreach ( array_keys( $sent_events ) as $key ) {
123 unset( $stored[ $key ] );
124 }
125 update_option( EventRecorder::OPTION_NAME, $stored, false );
126 }
127 }
128 update_option( Config::OPTION_SESSION_DURATIONS, array(), false );
129 }
130
131 /**
132 * Unschedule cron (call when disabling tracking).
133 */
134 public function unschedule() {
135 $this->scheduler->unschedule();
136 }
137
138 /**
139 * Record active day and optionally settings_page_viewed when on a CFF admin page.
140 */
141 public function maybe_record_active_day( $screen ) {
142 if ( ! $screen || strpos( $screen->id, 'cff' ) === false ) {
143 return;
144 }
145 if ( ! Config::is_enabled() ) {
146 return;
147 }
148 EventRecorder::record_active_day();
149 if ( isset( $screen->id ) && strpos( $screen->id, 'cff-settings' ) !== false ) {
150 EventRecorder::record( 'settings_page_viewed' );
151 }
152 }
153
154 /**
155 * AJAX: record a single event from JS (e.g. setup_wizard_started).
156 */
157 public function ajax_record_event() {
158 check_ajax_referer( 'cff_smash_usage_record_event', 'nonce' );
159 if ( ! current_user_can( 'manage_custom_facebook_feed_options' ) && ! current_user_can( 'manage_options' ) ) {
160 wp_send_json_error();
161 }
162 $event_name = isset( $_POST['event_name'] ) ? sanitize_text_field( wp_unslash( $_POST['event_name'] ) ) : '';
163 $allowed = array(
164 'setup_wizard_started',
165 'setup_wizard_step_completed',
166 'setup_wizard_completed',
167 'setup_wizard_abandoned',
168 'upgrade_prompt_shown',
169 );
170 if ( '' !== $event_name && in_array( $event_name, $allowed, true ) ) {
171 EventRecorder::record( $event_name );
172 }
173 wp_send_json_success();
174 }
175
176 /**
177 * AJAX: record session duration from JS (seconds).
178 */
179 public function ajax_record_session() {
180 check_ajax_referer( 'cff_smash_usage_record_session', 'nonce' );
181 if ( ( ! current_user_can( 'manage_custom_facebook_feed_options' ) && ! current_user_can( 'manage_options' )) || ! Config::is_enabled() ) {
182 wp_send_json_error();
183 }
184 $seconds = isset( $_POST['duration_seconds'] ) ? (int) $_POST['duration_seconds'] : 0;
185 EventRecorder::record_session_duration( $seconds );
186 wp_send_json_success();
187 }
188
189 /**
190 * Enqueue session-duration and record-event script on CFF admin pages.
191 */
192 public function enqueue_session_script() {
193 if ( ! function_exists( 'get_current_screen' ) ) {
194 return;
195 }
196 $screen = get_current_screen();
197 if ( ! $screen || strpos( $screen->id, 'cff' ) === false ) {
198 return;
199 }
200 $min = defined( 'CFF_MIN' ) && CFF_MIN ? '.min' : '';
201 $script_path = 'admin/assets/js/smash-usage-session' . $min . '.js';
202 $path = dirname( __DIR__, 2 ) . '/' . $script_path;
203 if ( ! file_exists( $path ) ) {
204 $script_path = 'admin/assets/js/smash-usage-session.js';
205 $path = dirname( __DIR__, 2 ) . '/' . $script_path;
206 }
207 if ( ! file_exists( $path ) ) {
208 return;
209 }
210 wp_enqueue_script(
211 'cff-smash-usage-session',
212 CFF_PLUGIN_URL . $script_path,
213 array( 'jquery' ),
214 defined( 'CFFVER' ) ? CFFVER : '1.0',
215 true
216 );
217 wp_localize_script(
218 'cff-smash-usage-session',
219 'cffSmashUsageSession',
220 array(
221 'ajax_url' => admin_url( 'admin-ajax.php' ),
222 'nonce' => wp_create_nonce( 'cff_smash_usage_record_session' ),
223 'event_nonce' => wp_create_nonce( 'cff_smash_usage_record_event' ),
224 )
225 );
226 }
227
228 /**
229 * Build the usage report payload without sending (for preview/debugging).
230 *
231 * @return array
232 */
233 public function get_payload_preview() {
234 $period_end = gmdate( 'Y-m-d', time() - DAY_IN_SECONDS );
235 $period_start = gmdate( 'Y-m-d', time() - 7 * DAY_IN_SECONDS );
236
237 return $this->payload_builder->build( 'preview-no-api', $period_start, $period_end );
238 }
239 }
240