PluginProbe ʕ •ᴥ•ʔ
WP STAGING – WordPress Backup, Restore, Migration & Clone / 3.3.1
WP STAGING – WordPress Backup, Restore, Migration & Clone v3.3.1
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 / AnalyticsConsent.php
wp-staging / Framework / Analytics Last commit date
Actions 3 years ago AnalyticsCleanup.php 4 years ago AnalyticsConsent.php 2 years ago AnalyticsEventDto.php 3 years ago AnalyticsSender.php 2 years ago WithAnalyticsAPI.php 4 years ago WithAnalyticsSiteInfo.php 2 years ago
AnalyticsConsent.php
229 lines
1 <?php
2
3 namespace WPStaging\Framework\Analytics;
4
5 use WPStaging\Framework\Notices\Notices;
6 use WPStaging\Core\WPStaging;
7
8 use function WPStaging\functions\debug_log;
9
10 class AnalyticsConsent
11 {
12 use WithAnalyticsAPI;
13
14 const OPTION_NAME_ANALYTICS_HAS_CONSENT = 'wpstg_analytics_has_consent';
15 const OPTION_NAME_ANALYTICS_NOTICE_DISMISSED = 'wpstg_analytics_notice_dismissed';
16 const OPTION_NAME_ANALYTICS_MODAL_DISMISSED = 'wpstg_analytics_modal_dismissed';
17 const OPTION_NAME_ANALYTICS_REMIND_ME = 'wpstg_analytics_consent_remind_me';
18
19 /**
20 * Shows the admin notice asking the user whether he consents to sending usage information to WP STAGING.
21 * @action admin_notices
22 */
23 public function maybeShowConsentNotice()
24 {
25 // Early bail: Not a WP STAGING page
26 if (!WPStaging::make(Notices::class)->isWPStagingAdminPage()) {
27 return;
28 }
29
30 // Early bail: User does not have enough access to consent, or has consented already.
31 if (!current_user_can('manage_options') || get_option(self::OPTION_NAME_ANALYTICS_NOTICE_DISMISSED)) {
32 return;
33 }
34
35 $remindMe = get_option(self::OPTION_NAME_ANALYTICS_REMIND_ME);
36
37 if (!empty($remindMe) && time() < $remindMe) {
38 return;
39 }
40
41 $notice = WPSTG_PLUGIN_DIR . '/Backend/views/notices/analytics-consent.php';
42
43 if (!file_exists($notice)) {
44 return;
45 }
46
47 include_once $notice;
48 }
49
50 /**
51 * If the request that sends the consent fails, we show a notice to let the user know.
52 * @action admin_notices
53 */
54 public function maybeShowConsentFailureNotice()
55 {
56 // Early bail: Not a WP STAGING page
57 if (!WPStaging::make(Notices::class)->isWPStagingAdminPage()) {
58 return;
59 }
60
61 // Early bail
62 if (!isset($_GET['wpstgConsentFailed'])) {
63 return;
64 }
65
66 $notice = WPSTG_PLUGIN_DIR . '/Backend/views/notices/analytics-consent-failed.php';
67
68 if (!file_exists($notice)) {
69 return;
70 }
71
72 include_once $notice;
73 }
74
75 /**
76 * Listens for whether the user has given or denied consent to send usage information.
77 * @action admin_init
78 */
79 public function listenForConsent()
80 {
81 // Early bail: Not a consent request
82 if (!isset($_GET['wpstgConsent'])) {
83 return;
84 }
85
86 // Early bail: Not enough permissions
87 if (!current_user_can('manage_options')) {
88 return;
89 }
90
91 // Early bail: Invalid nonce
92 check_ajax_referer('wpstg_consent_nonce', 'wpstgConsentNonce');
93
94 if ($_GET['wpstgConsent'] == 'later') {
95 update_option(self::OPTION_NAME_ANALYTICS_REMIND_ME, strtotime('+7 days'), false);
96
97 return;
98 }
99
100 // Early bail: User has not consented
101 if ($_GET['wpstgConsent'] == 'no') {
102 update_option(self::OPTION_NAME_ANALYTICS_NOTICE_DISMISSED, '1', false);
103 update_option(self::OPTION_NAME_ANALYTICS_MODAL_DISMISSED, '1', false);
104 update_option(self::OPTION_NAME_ANALYTICS_HAS_CONSENT, '0', false);
105 delete_option(self::OPTION_NAME_ANALYTICS_REMIND_ME);
106
107 add_action('admin_notices', [$this, 'showNoticeConsentRefused']);
108
109 return;
110 }
111
112 if ($_GET['wpstgConsent'] == 'yes') {
113 try {
114 $this->giveConsent();
115 } catch (\Exception $e) {
116 // Show notice informing the user
117 wp_redirect(add_query_arg([
118 'wpstgConsentFailed' => true,
119 ], $this->getReturnUrl()));
120 exit;
121 }
122
123 update_option(self::OPTION_NAME_ANALYTICS_NOTICE_DISMISSED, '1', false);
124 update_option(self::OPTION_NAME_ANALYTICS_MODAL_DISMISSED, '1', false);
125 update_option(self::OPTION_NAME_ANALYTICS_HAS_CONSENT, '1', false);
126 delete_option(self::OPTION_NAME_ANALYTICS_REMIND_ME);
127 }
128 }
129
130 public function showNoticeConsentRefused()
131 {
132 $notice = WPSTG_PLUGIN_DIR . '/Backend/views/notices/analytics-consent-refused.php';
133
134 if (!file_exists($notice)) {
135 return;
136 }
137
138 include_once $notice;
139 }
140
141 /**
142 * Registers the consent on the Analytics database
143 *
144 * @throws \Exception
145 */
146 public function giveConsent()
147 {
148 $url = $this->getApiUrl('consent');
149
150 $response = wp_remote_post($url, [
151 'method' => 'POST',
152 'headers' => ['Content-Type' => 'application/json; charset=utf-8'],
153 'body' => json_encode([
154 'site_hash' => $this->getSiteHash(),
155 'site_url' => get_home_url(),
156 ]),
157 'data_format' => 'body',
158 'timeout' => 10,
159 'redirection' => 5,
160 'httpversion' => '1.0',
161 'blocking' => true,
162 'sslverify' => false,
163 ]);
164
165 // Early bail: Something went wrong with the consent request.
166 if (is_wp_error($response) || !in_array(wp_remote_retrieve_response_code($response), [201, 409])) {
167 $errorMessage = is_wp_error($response) ? $response->get_error_message() : wp_remote_retrieve_body($response);
168 debug_log('WP STAGING Analytics Send Error: ' . $errorMessage, 'debug');
169
170 // Dismiss the consent notice so that it doesn't appear anymore
171 update_option(self::OPTION_NAME_ANALYTICS_NOTICE_DISMISSED, '1', false);
172
173 // Dismiss the consent modal so that id doesn't appear anymore
174 update_option(self::OPTION_NAME_ANALYTICS_MODAL_DISMISSED, '1', false);
175
176 // give consent to be able to send data when network is back
177 update_option(self::OPTION_NAME_ANALYTICS_HAS_CONSENT, '1', false);
178
179 throw new \Exception();
180 }
181 }
182
183 /**
184 * @return bool|null Whether the user has consented to the Analytics. Null if didn't answer.
185 */
186 public function hasUserConsent()
187 {
188 return get_option(self::OPTION_NAME_ANALYTICS_HAS_CONSENT, null);
189 }
190
191 /**
192 * Invalidate the fact that the user has consented.
193 * @todo remove this after testing
194 */
195 public function invalidateConsent()
196 {
197 delete_option(self::OPTION_NAME_ANALYTICS_NOTICE_DISMISSED);
198 delete_option(self::OPTION_NAME_ANALYTICS_HAS_CONSENT);
199 }
200
201 protected function getReturnUrl(): string
202 {
203 global $pagenow, $plugin_page;
204
205 return add_query_arg('page', $plugin_page, admin_url($pagenow));
206 }
207
208 /**
209 * @param bool $agreeOrDecline True to generate a link that agrees to send usage information. False to generate a link that disagrees.
210 *
211 * @return string The link to either agree or decline analytics.
212 */
213 public function getConsentLink(bool $agreeOrDecline): string
214 {
215 return add_query_arg([
216 'wpstgConsent' => $agreeOrDecline ? 'yes' : 'no',
217 'wpstgConsentNonce' => wp_create_nonce('wpstg_consent_nonce'),
218 ], $this->getReturnUrl());
219 }
220
221 public function getRemindMeLaterConsentLink(): string
222 {
223 return add_query_arg([
224 'wpstgConsent' => 'later',
225 'wpstgConsentNonce' => wp_create_nonce('wpstg_consent_nonce'),
226 ], $this->getReturnUrl());
227 }
228 }
229