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