PluginProbe
The GDPR Framework By Data443 / trunk
The GDPR Framework By Data443 vtrunk
2.5.0 2.4.0 trunk 1.0.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.3 1.0.33 1.0.34 1.0.35 1.0.36 1.0.37 1.0.39 1.0.4 1.0.40 1.0.41 1.0.42 1.0.43 1.0.44 1.0.45 1.0.46 All 41 releases
gdpr-framework / src / Components / Consent / ConsentManager.php

ConsentManager.php in The GDPR Framework By Data443 trunk, at src/Components/Consent/ConsentManager.php

470 lines 14.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Codelight\GDPR\Components\Consent;
4
5 if ( ! defined( 'ABSPATH' ) ) exit;
6
7 /**
8 * Handles getting, saving and removing consent based on a whitelist
9 *
10 * Class ConsentManager
11 *
12 * @package Codelight\GDPR\Components\Consent
13 */
14 class ConsentManager
15 {
16 /* @var UserConsentModel */
17 protected $model;
18
19 /* @var array */
20 protected $defaultConsentTypes = [];
21
22 /* @var array */
23 protected $customConsentTypes = [];
24
25 /**
26 * ConsentManager constructor.
27 *
28 * @param UserConsentModel $model
29 */
30 public function __construct(UserConsentModel $model)
31 {
32 $this->model = $model;
33
34 add_action('init', [$this, 'registerCustomConsentTypes'], 0);
35 add_action('init', [$this, 'registerDefaultConsentTypes'], 0);
36
37 add_filter('gdpr/data-subject/data', [$this, 'getdata'], 20, 2);
38 add_action('gdpr/data-subject/delete', [$this, 'delete']);
39 add_action('gdpr/data-subject/anonymize', [$this, 'anonymize'], 10, 2);
40 }
41
42 public function registerDefaultConsentTypes()
43 {
44 global $gdpr;
45
46 /****
47 * privacy-policy default consent
48 */
49 $policyPageUrl = get_permalink($gdpr->Options->get('policy_page'));
50 add_filter( 'gdpr_custom_policy_link', 'gdprfPrivacyPolicyurl' );
51
52 $policyPageUrl = apply_filters( 'gdpr_custom_policy_link',$policyPageUrl);
53
54 // Fix (PR review Finding 4): build the built-in link with an escaped
55 // URL and rel="noopener noreferrer" (target="_blank" without it leaks
56 // window.opener). The title is rendered through wp_kses() with the
57 // gdpr_allowed_consent_title_html() allow-list in the views.
58 $policyPageUrl = esc_url( $policyPageUrl );
59
60 $gdpr->Consent->register(
61 'privacy-policy',
62 sprintf(
63 __('I accept the %sPrivacy Policy%s', 'gdpr-framework'),
64 '<a href="' . $policyPageUrl . '" target="_blank" rel="noopener noreferrer">',
65 "</a>"
66 ),
67 _x('This consent is not visible by default. If someone wishes to withdraw it, they should simply request to delete all their data.', '(Admin)', 'gdpr-framework'),
68 false
69 );
70
71 /****
72 * privacy-policy do-not-sell-request form default consent
73 */
74
75 $this->register(
76 'do-not-sell-info',
77 sprintf(
78 __( 'Do Not Sell My Data', 'gdpr-framework' )
79 ),
80 _x( 'I do not consent to having my information sold by ' , '(Admin)', 'gdpr-framework' ) .get_bloginfo('name'). '.',
81 true
82 );
83
84 $this->register(
85 'receive-communications',
86 sprintf(
87 __( 'Receive Communications from ', 'gdpr-framework' ) . get_bloginfo('name')
88 ),
89 _x( 'I agree to receive other communications from ' , '(Admin)', 'gdpr-framework' ) .get_bloginfo('name'). '.',
90 true
91 );
92
93 /****
94 * terms-conditions default consent
95 */
96 $termsPage = $gdpr->Options->get('terms_page');
97 if ($termsPage) {
98 $termsPageUrl = get_permalink($termsPage);
99 } else {
100 $termsPageUrl = false;
101 }
102
103 if ($termsPageUrl) {
104 // Fix (PR review Finding 4): see the privacy-policy link above.
105 $termsPageUrl = esc_url( $termsPageUrl );
106 $gdpr->Consent->register(
107 'terms-conditions',
108 sprintf(
109 __('I accept the %sTerms & Conditions%s', 'gdpr-framework'),
110 '<a href="' . $termsPageUrl . '" target="_blank" rel="noopener noreferrer">',
111 "</a>"
112 ),
113 _x('This consent is not visible by default. If someone wishes to withdraw it, they should simply request to delete all their data.', '(Admin)', 'gdpr-framework'),
114 false
115 );
116 }
117
118 $this->register(
119 'gdpr_cookie_consent',
120 _x( 'Site Cookie Consent', '(Admin)', 'gdpr-framework' ),
121 _x( 'This consent is not visible by default. If someone wishes to withdraw it, they should simply request to delete all their data.', '(Admin)', 'gdpr-framework' ),
122 false
123 );
124
125 /****
126 * Woocommerce Policy consent
127 */
128 if ( class_exists( 'WooCommerce' ) ) {
129 $gdpr->Consent->register(
130 'gdpr_woo_consent', _x('Woocommerce Policy Consent', '(Admin)', 'gdpr-framework'),
131 _x('This consent is visible by default on woocommerce checkout page. If someone wishes to withdraw it, they should simply request to delete all their data.', '(Admin)', 'gdpr-framework'),
132 true
133 );
134 }
135 }
136
137 /**
138 * Get a list of all registered consent types
139 *
140 * @return array
141 */
142 public function getConsentTypes()
143 {
144 return apply_filters('gdpr/consent/types', $this->getDefaultConsentTypes() + $this->getCustomConsentTypes());
145 }
146
147 /**
148 * Get all consent types registered by external sources, i.e. not stored in the database
149 *
150 * @return array
151 */
152 public function getDefaultConsentTypes()
153 {
154 return apply_filters('gdpr/consent/types/default', $this->defaultConsentTypes);
155 }
156
157 /**
158 * Get all consent types registered by the admin, i.e. stored in the database
159 *
160 * @return array
161 */
162 public function getCustomConsentTypes()
163 {
164 return apply_filters('gdpr/consent/types/custom', $this->customConsentTypes);
165 }
166
167 /**
168 * Register a *default* consent in the list of valid consents
169 *
170 * @param $consent
171 */
172 public function register($slug, $title, $description, $visible = true)
173 {
174 $this->defaultConsentTypes[$slug] = [
175 'slug' => $slug,
176 'title' => $title,
177 'description' => $description,
178 'visible' => $visible,
179 ];
180 }
181
182 /**
183 * Register consent types saved via WP admin
184 */
185 public function registerCustomConsentTypes()
186 {
187 global $gdpr;
188
189 $savedConsentTypes = $gdpr->Options->get('consent_types');
190
191 if (is_array($savedConsentTypes) && count($savedConsentTypes))
192 {
193 foreach ($savedConsentTypes as $consentType)
194 {
195 /* FRAM-135 check for the slug key before the reference */
196 if (!empty($consentType['slug'])) {
197 $this->customConsentTypes[$consentType['slug']] = [
198 'slug' => isset($consentType['slug']) ? $consentType['slug'] : '',
199 'title' => isset($consentType['title']) ? $consentType['title'] : '',
200 'description' => isset($consentType['description']) ? $consentType['description'] : '',
201 'visible' => isset($consentType['visible']) ? $consentType['visible'] : '',
202 ];
203 }
204 }
205 }
206 }
207
208 /**
209 * Save the given consent types to database
210 *
211 * @param $consentTypes
212 */
213 public function saveCustomConsentTypes($consentTypes)
214 {
215 global $gdpr;
216
217 $gdpr->Options->set('consent_types', $consentTypes);
218 }
219
220 /**
221 * Check if a consent is valid so that we don't write random stuff in the database by accident
222 *
223 * @param $consent
224 * @return bool
225 */
226 public function isRegisteredConsent($consent)
227 {
228 // Fix: this used to read `null !== $this->getConsentTypes($consent)`.
229 // getConsentTypes() takes no parameters and always returns an array, so
230 // the comparison was always true and the whitelist never rejected
231 // anything -- including $_REQUEST['consent'] forwarded verbatim by
232 // PrivacyToolsPageController::withdrawConsent() and the Contact Form 7
233 // acceptance-field names checked in ContactForm7::getConsentFields().
234 $consentTypes = $this->getConsentTypes();
235
236 if (!is_array($consentTypes)) {
237 return false;
238 }
239
240 return array_key_exists($consent, $consentTypes);
241 }
242
243 /**
244 * Set a consent as 'given' for the data subject
245 *
246 * @param $email
247 * @param $consent
248 */
249 public function giveConsent($email, $consent, $valid_until = null)
250 {
251 if ($this->isRegisteredConsent($consent)) {
252 $validation = apply_filters('gdpr/consent/give', true, $email, $consent);
253
254 // If the data subject has already given this consent, do nothing
255 if ($this->model->given($email, $consent) || !$validation) {
256 return;
257 }
258
259 $this->model->give($email, $consent, $valid_until);
260 do_action('gdpr/consent/given', $email, $consent);
261 }
262 }
263
264 /**
265 * Set a consent as withdrawn for the data subject
266 *
267 * @param $email
268 * @param $consent
269 */
270 public function withdrawConsent($email, $consent)
271 {
272 if ($this->isRegisteredConsent($consent)) {
273 $validation = apply_filters('gdpr/consent/withdraw', true, $email, $consent);
274
275 // If the consent has never been given or if data subject has already withdrawn this consent, do nothing
276 if (!$this->model->exists($email, $consent) || $this->model->withdrawn($email, $consent) || !$validation) {
277 return;
278 }
279
280 $this->model->withdraw($email, $consent);
281 do_action('gdpr/consent/withdrawn', $email, $consent, 'withdrawn');
282 }
283 }
284
285 /**
286 * Remove consent given by subject
287 *
288 * @param $email
289 * @param $consent
290 */
291 public function deleteConsent($email, $consent)
292 {
293 // Deliberately NOT gated on isRegisteredConsent(). This is the erasure
294 // path -- delete() below feeds it slugs read straight out of the
295 // database, never caller input -- and a consent type can stop being
296 // registered while its rows remain (a custom type the admin removed,
297 // or 'gdpr_woo_consent' once WooCommerce is deactivated). Skipping
298 // those rows would leave the data subject's email in the table after
299 // they asked to be forgotten.
300 if ($this->model->given($email, $consent)) {
301 do_action('gdpr/consent/withdrawn', $email, $consent, 'deleted');
302 }
303
304 $this->model->delete($email, $consent);
305 }
306
307 /**
308 * Withdraw and anonymize a consent
309 *
310 * @param $email
311 * @param $consent
312 * @param $anonymizedId
313 */
314 public function anonymizeConsent($email, $consent, $anonymizedId)
315 {
316 // Not gated on isRegisteredConsent() -- see deleteConsent() above for
317 // why the erasure path must cover every stored row.
318 if ($this->model->given($email, $consent)) {
319 do_action('gdpr/consent/withdrawn', $email, $consent, 'anonymized');
320 }
321
322 $this->model->anonymize($email, $consent, $anonymizedId);
323 }
324
325 /**
326 * Get all consent given by subject
327 *
328 * @param $email
329 */
330 public function getAllConsents($email)
331 {
332 return $this->model->getAll($email);
333 }
334
335 /**
336 * Get all consent given by subject with other data
337 *
338 * @param $email
339 */
340 public function getAllConsentswithdetails($email)
341 {
342 return $this->model->getAllwithdetails($email);
343 }
344
345 /**
346 * Get all logs deleted for user
347 *
348 * @param $id
349 */
350 public function gdpr_delete_log($id)
351 {
352 return $this->model->deletelog($id);
353 }
354
355 /**
356 * Get all user logs
357 *
358 * @param $email
359 */
360 public function getuserlogsData($email)
361 {
362 $usefromemail = get_user_by( 'email', $email );
363 return $this->model->getuserlogs($usefromemail->data->ID);
364 }
365
366 /**
367 * Get the registered consent types and add 'given' field depending
368 * on whether or not the user has given this particular consent
369 *
370 * @param $dataSubjectConsents
371 * @return array
372 */
373 public function getConsentData($dataSubjectConsents)
374 {
375 $consentTypes = $this->getConsentTypes();
376 $consents = [];
377
378 if($dataSubjectConsents){
379 foreach ($dataSubjectConsents as $consent => $subjectConsentType){
380 $subjectConsentTypeArray[$subjectConsentType->consent] = $subjectConsentType->consent;
381 $subjectConsentUntilArray[$subjectConsentType->consent] = $subjectConsentType->valid_until;
382
383 }
384 foreach ($consentTypes as $slug => $consentType)
385 {
386 if (in_array($slug, $subjectConsentTypeArray))
387 {
388 $consents[$slug] = $consentType;
389 $consents[$slug]['valid_until'] = $subjectConsentUntilArray[$slug];
390 }
391 }
392 }
393 return $consents;
394 }
395
396 public function getbySlugConsent($dataSubjectConsents)
397 {
398 if(isset($dataSubjectConsents) && !empty($dataSubjectConsents)){
399 $dataSubjectConsents=sanitize_key($dataSubjectConsents);
400 $consentTypes = $this->getConsentTypes();
401 foreach ($consentTypes as $slug => $consentType)
402 {
403 if ($slug === $dataSubjectConsents)
404 {
405 return $consentType;
406 }
407 }
408 }
409 }
410
411 /**
412 * Return a list of all data subjects who have given a particular consent
413 *
414 * @param $consent
415 */
416 public function getAllDataSubjectsByConsent($consent)
417 {
418 // Todo
419 }
420
421 /**
422 * Return a list of all consent with other data
423 *
424 * @param $data and $email
425 */
426 public function getdata(array $data, $email)
427 {
428 $consents = $this->getAllConsentswithdetails($email);
429 if(!empty($consents))
430 {
431 $title = __('Consent Information', 'gdpr');
432 foreach ($consents as $i => $consent)
433 {
434 $data[$title][$i]['consent'] = $consent->consent;
435 $data[$title][$i]['updated_at'] = $consent->updated_at;
436 $data[$title][$i]['ip'] = $consent->ip;
437 }
438 }
439 return $data;
440 }
441 /**
442 * Withdraw and delete all consents given by a data subject
443 *
444 * @param $email
445 */
446 public function delete($email)
447 {
448 $consents = $this->getAllConsents($email);
449 foreach ($consents as $consent)
450 {
451 $this->deleteConsent($email, $consent->consent);
452 }
453 }
454
455 /**
456 * Withdraw and anonymize all consents given by a data subject
457 *
458 * @param $email
459 * @param $anonymizedId
460 */
461 public function anonymize($email, $anonymizedId)
462 {
463 $consents = $this->getAllConsents($email);
464 foreach ($consents as $consent)
465 {
466 $this->anonymizeConsent($email, $consent->consent, $anonymizedId);
467 }
468 }
469 }
470