PluginProbe ʕ •ᴥ•ʔ
WP STAGING – WordPress Backup, Restore, Migration & Clone / 3.8.2
WP STAGING – WordPress Backup, Restore, Migration & Clone v3.8.2
4.9.1 4.9.0 4.8.1 trunk 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.1.0 3.1.1 3.1.2 3.1.3 3.1.4 3.10.0 3.2.0 3.3.1 3.3.2 3.3.3 3.4.1 3.4.3 3.5.0 3.6.0 3.7.1 3.8.0 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.8.6 3.8.7 3.9.0 3.9.1 3.9.2 3.9.3 3.9.4 4.0.0 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 4.2.0 4.2.1 4.3.0 4.3.1 4.3.2 4.4.0 4.5.0 4.6.0 4.7.0 4.7.1 4.7.2 4.7.3 4.8.0
wp-staging / Framework / Analytics / AnalyticsSender.php
wp-staging / Framework / Analytics Last commit date
Actions 2 years ago AnalyticsCleanup.php 4 years ago AnalyticsConsent.php 2 years ago AnalyticsEventDto.php 2 years ago AnalyticsSender.php 2 years ago WithAnalyticsAPI.php 4 years ago WithAnalyticsSiteInfo.php 2 years ago
AnalyticsSender.php
179 lines
1 <?php
2
3 namespace WPStaging\Framework\Analytics;
4
5 class AnalyticsSender
6 {
7 use WithAnalyticsAPI;
8
9 protected $consent;
10
11 private $corruptSettingsNotice;
12
13 public function __construct(AnalyticsConsent $consent)
14 {
15 $this->consent = $consent;
16 }
17
18 public function maybeSend()
19 {
20 // Early bail: Do not run on AJAX requests.
21 if (defined('DOING_AJAX') && DOING_AJAX) {
22 return;
23 }
24
25 // We store the analytics sending time at "wpstg_settings"
26 // since this runs on every request, and it's an autoloaded option.
27 // Also, the value we need to store in it is small.
28 $settings = get_option("wpstg_settings", []);
29
30 // convert settings from type object to array
31 if (is_object($settings)) {
32 $settings = json_decode(json_encode($settings), true);
33 }
34
35 // If still $settings is not array, bail
36 if (!is_array($settings)) {
37 return;
38 }
39
40 // Interval to wait before sending events.
41 $interval = 15 * MINUTE_IN_SECONDS;
42
43 // Early bail: Sent not so long ago.
44 if (isset($settings['lastAnalyticsSend']) && time() - $settings['lastAnalyticsSend'] - $interval < 0) {
45 return;
46 }
47
48 $settings['lastAnalyticsSend'] = time();
49
50 if (!update_option('wpstg_settings', $settings)) {
51 \WPStaging\functions\debug_log('WP STAGING: Could not update Analytics last sent time.', 'debug');
52 };
53
54 $this->sendAnalytics();
55 }
56
57 public function sendAnalytics()
58 {
59 global $wpdb;
60
61 $eventOptions = $wpdb->get_results("SELECT * FROM $wpdb->options WHERE `option_name` LIKE 'wpstg_analytics_event_%' LIMIT 0, 20");
62
63 // Nothing to send.
64 if (empty($eventOptions)) {
65 return;
66 }
67
68 // Early bail: User has not given consent to send analytics
69 if (!$this->consent->hasUserConsent()) {
70 return;
71 }
72
73 // Format the events to the expected format
74 $events = array_map(function ($eventOption) {
75 return json_decode($eventOption->option_value);
76 }, $eventOptions);
77
78 $this->setStaleEvents($events);
79
80 // Filter the events to send only those that are ready to be sent
81 $events = array_filter($events, function ($event) {
82 return $event->ready_to_send;
83 });
84
85 // Early bail: No events ready to be sent
86 if (empty($events)) {
87 return;
88 }
89
90 // Convert true to 1 and false to 0 for MySQL TinyInt
91 foreach ($events as &$event) {
92 foreach ($event as $property => &$value) {
93 if (is_bool($value)) {
94 $event->$property = (int)$value;
95 } elseif ($property === 'site_info') {
96 $siteInfo = &$value;
97
98 foreach ($siteInfo as $siteInfoProperty => &$siteInfoValue) {
99 if (is_bool($siteInfoValue)) {
100 $siteInfo->$siteInfoProperty = (int)$siteInfoValue;
101 }
102 }
103 }
104 }
105 }
106
107 // Delete the events, regardless of whether it succeeded or failed to send.
108 // This prevents events from hanging and being sent every time if they are in an invalid format or something goes wrong.
109 $idsToDelete = implode(',', array_map(function ($eventOption) {
110 return $eventOption->option_id;
111 }, $eventOptions));
112
113 if (!$wpdb->query("DELETE FROM $wpdb->options WHERE `option_id` IN ($idsToDelete)")) {
114 \WPStaging\functions\debug_log('WP STAGING Analytics Delete Sent Events Error: ' . $wpdb->last_error);
115 }
116
117 $body = wp_json_encode([
118 'events' => $events,
119 'site_hash' => $this->getSiteHash(),
120 ]);
121
122 $url = $this->getApiUrl('events');
123
124 // Early bail: Do not dispatch events when in dev mode, unless allowed.
125 if (defined('WPSTG_DEV') && WPSTG_DEV) {
126 if (!defined('WPSTG_DEV_SEND_ANALYTICS') || defined('WPSTG_DEV_SEND_ANALYTICS') && !WPSTG_DEV_SEND_ANALYTICS) {
127 return;
128 }
129 }
130
131 $response = wp_remote_post($url, [
132 'method' => 'POST',
133 'headers' => ['Content-Type' => 'application/json; charset=utf-8'],
134 'body' => $body,
135 'data_format' => 'body',
136 'timeout' => 10,
137 'redirection' => 5,
138 'httpversion' => '1.0',
139 'blocking' => true,
140 'sslverify' => false,
141 ]);
142
143 if (is_wp_error($response) || wp_remote_retrieve_response_code($response) !== 200) {
144 if (wp_remote_retrieve_response_code($response) == 412) {
145 // The site hash does not exist in the Analytics database. We need to ask for consent again.
146 if ($this->consent->hasUserConsent()) {
147 try {
148 $this->consent->giveConsent();
149 } catch (\Exception $e) {
150 // We could not re-validate the consent.
151 // Don't do anything here.
152 // E.g. If user gives his consent but wp-staging.com is not reachable
153 // we should save the setting and fail silently. Next time wp-staging.com is available again we automatically can send usage information.
154 // No need then to ask again for consent.
155 }
156 }
157 }
158
159 $errorMessage = is_wp_error($response) ? $response->get_error_message() : wp_remote_retrieve_body($response);
160 \WPStaging\functions\debug_log('WP STAGING Analytics Send Error: ' . $errorMessage);
161 }
162 }
163
164 /**
165 * Mark as stale the events that started longer than 1 day ago but isn't ready to send yet
166 *
167 * @param $events
168 */
169 protected function setStaleEvents(&$events)
170 {
171 foreach ($events as &$event) {
172 if (!$event->ready_to_send && $event->start_time < time() - 1 * DAY_IN_SECONDS) {
173 $event->ready_to_send = true;
174 $event->is_stale = true;
175 }
176 }
177 }
178 }
179