PluginProbe
GDPR / 2.0.1
GDPR v2.0.1
trunk 1.4.7 2.0.0 2.0.1 2.0.10 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.1.1 2.1.2
gdpr / includes / class-gdpr.php

class-gdpr.php in GDPR 2.0.1, at includes/class-gdpr.php

676 lines 24.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * The file that defines the core plugin class
5 *
6 * A class definition that includes attributes and functions used across both the
7 * public-facing side of the site and the admin area.
8 *
9 * @link https://trewknowledge.com
10 * @since 1.0.0
11 *
12 * @package GDPR
13 * @subpackage includes
14 * @author Fernando Claussen <fernandoclaussen@gmail.com>
15 */
16
17 /**
18 * The core plugin class.
19 *
20 * This is used to define internationalization, admin-specific hooks, and
21 * public-facing site hooks.
22 *
23 * Also maintains the unique identifier of this plugin as well as the current
24 * version of the plugin.
25 *
26 * @since 1.0.0
27 * @package GDPR
28 * @subpackage includes
29 * @author Fernando Claussen <fernandoclaussen@gmail.com>
30 */
31 class GDPR {
32
33 /**
34 * The unique identifier of this plugin.
35 *
36 * @since 1.0.0
37 * @author Fernando Claussen <fernandoclaussen@gmail.com>
38 * @access protected
39 * @var string $plugin_name The string used to uniquely identify this plugin.
40 */
41 protected $plugin_name;
42
43 /**
44 * The current version of the plugin.
45 *
46 * @since 1.0.0
47 * @author Fernando Claussen <fernandoclaussen@gmail.com>
48 * @access protected
49 * @var string $version The current version of the plugin.
50 */
51 protected $version;
52
53 /**
54 * Define the core functionality of the plugin.
55 *
56 * Set the plugin name and the plugin version that can be used throughout the plugin.
57 * Load the dependencies, define the locale, and set the hooks for the admin area and
58 * the public-facing side of the site.
59 *
60 * @since 1.0.0
61 * @author Fernando Claussen <fernandoclaussen@gmail.com>
62 */
63 public function __construct() {
64 if ( defined( 'GDPR_VERSION' ) ) {
65 $this->version = GDPR_VERSION;
66 } else {
67 $this->version = '1.0.0';
68 }
69 $this->plugin_name = 'gdpr';
70
71 $this->load_dependencies();
72 $this->define_common_hooks();
73 $this->define_admin_hooks();
74 $this->define_public_hooks();
75
76 if ( ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) OR ( defined( 'DOING_CRON' ) && DOING_CRON ) OR ( defined( 'DOING_AJAX' ) && DOING_AJAX ) OR ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) ) {
77 return;
78 }
79 }
80
81 /**
82 * Load the required dependencies for this plugin.
83 *
84 * @since 1.0.0
85 * @author Fernando Claussen <fernandoclaussen@gmail.com>
86 * @access private
87 */
88 private function load_dependencies() {
89 /**
90 * The class responsible for adding help tabs.
91 */
92 require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-gdpr-help.php';
93
94 /**
95 * The class responsible logging user actions.
96 */
97 require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-gdpr-audit-log.php';
98
99 /**
100 * The class responsible for defining the telemetry post type.
101 */
102 require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/class-gdpr-telemetry.php';
103
104 /**
105 * The class responsible for defining the requests section of the plugin.
106 */
107 require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-gdpr-requests.php';
108
109 /**
110 * The class responsible for defining the admin facing requests section of the plugin.
111 */
112 require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/class-gdpr-requests-admin.php';
113
114 /**
115 * The class responsible for defining the admin facing requests section of the plugin.
116 */
117 require_once plugin_dir_path( dirname( __FILE__ ) ) . 'public/class-gdpr-requests-public.php';
118
119 /**
120 * The class responsible for locating the email templates and sending emails.
121 */
122 require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-gdpr-email.php';
123
124 /**
125 * The class responsible for defining all actions that occur in the admin area.
126 */
127 require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/class-gdpr-admin.php';
128
129 /**
130 * The class responsible for defining all actions that occur in the public-facing
131 * side of the site.
132 */
133 require_once plugin_dir_path( dirname( __FILE__ ) ) . 'public/class-gdpr-public.php';
134
135 }
136
137 /**
138 * Define the locale for this plugin for internationalization.
139 * @since 1.0.0
140 * @author Fernando Claussen <fernandoclaussen@gmail.com>
141 */
142 public function set_locale() {
143
144 load_plugin_textdomain(
145 'gdpr',
146 false,
147 plugin_dir_url( dirname( __FILE__ ) ) . 'languages/'
148 );
149
150 }
151
152 /**
153 * Register all of the common hooks.
154 * @since 1.0.0
155 * @author Fernando Claussen <fernandoclaussen@gmail.com>
156 * @access private
157 */
158 private function define_common_hooks() {
159 add_action( 'wp_ajax_gdpr_generate_data_export', array( $this, 'export_data' ) );
160 }
161
162 /**
163 * Register all of the hooks related to the admin area functionality
164 * of the plugin.
165 *
166 * @since 1.0.0
167 * @author Fernando Claussen <fernandoclaussen@gmail.com>
168 * @access private
169 */
170 private function define_admin_hooks() {
171
172 $plugin_admin = new GDPR_Admin( $this->get_plugin_name(), $this->get_version() );
173 $requests_admin = new GDPR_Requests_Admin( $this->get_plugin_name(), $this->get_version() );
174 $telemetry = new GDPR_Telemetry( $this->get_plugin_name(), $this->get_version() );
175 $requests = new GDPR_Requests( $this->get_plugin_name(), $this->get_version() );
176 $plugin_emails = new GDPR_Email();
177 $woo_add_to_registration = get_option( 'gdpr_add_consent_checkboxes_registration', false );
178 $woo_add_to_checkout = get_option( 'gdpr_add_consent_checkboxes_checkout', false );
179
180 add_filter( 'nonce_user_logged_out', array( $this, 'woo_nonce_fix' ), 100, 2 );
181 add_action( 'plugins_loaded', array( $this, 'set_locale' ) );
182 add_action( 'bp_account_details_fields', array( __CLASS__, 'consent_checkboxes' ) );
183 if ( $woo_add_to_registration ) {
184 add_action( 'woocommerce_register_form', array( __CLASS__, 'consent_checkboxes' ) );
185 }
186 if ( $woo_add_to_checkout ) {
187 add_action( 'woocommerce_checkout_update_user_meta', array( $plugin_admin, 'woocommerce_checkout_save_consent' ), 10, 2 );
188 add_filter( 'woocommerce_checkout_fields', array( $plugin_admin, 'woocommerce_consent_checkboxes' ) );
189 }
190 add_filter( 'manage_users_custom_column', array( $plugin_admin, 'add_consents_to_consents_column' ), 10, 3 );
191 add_filter( 'manage_users_columns', array( $plugin_admin, 'add_consents_column_to_user_table' ) );
192 add_action( 'show_user_profile', array( $plugin_admin, 'edit_user_profile' ) );
193 add_action( 'personal_options_update', array( $plugin_admin, 'user_profile_update' ) );
194 add_action( 'admin_notices', array( $plugin_admin, 'policy_updated_notice' ) );
195 add_action( 'admin_notices', array( $plugin_admin, 'review_settings_after_v2_notice' ) );
196 add_action( 'upgrader_process_complete', array( $plugin_admin, 'upgrade_completed' ), 10, 2 );
197 add_action( 'wp_ajax_ignore_policy_update', array( $plugin_admin, 'ignore_policy_update' ) );
198 add_action( 'wp_ajax_seek_consent', array( $plugin_admin, 'seek_consent' ) );
199 add_action( 'publish_page', array( $plugin_admin, 'policy_updated' ), 10, 2 );
200 add_action( 'admin_enqueue_scripts', array( $plugin_admin, 'enqueue_styles' ) );
201 add_action( 'admin_enqueue_scripts', array( $plugin_admin, 'enqueue_scripts' ) );
202 add_action( 'admin_menu', array( $plugin_admin, 'add_menu' ) );
203 add_action( 'admin_init', array( $plugin_admin, 'register_settings' ) );
204 add_action( 'register_form', array( __CLASS__, 'consent_checkboxes' ) );
205 add_action( 'registration_errors', array( $plugin_admin, 'registration_errors' ), 10, 3 );
206 add_action( 'user_register', array( __CLASS__, 'save_user_consent_on_registration' ) );
207 add_action( 'wp_ajax_gdpr_access_data', array( $plugin_admin, 'access_data' ) );
208 add_action( 'wp_ajax_gdpr_audit_log', array( $plugin_admin, 'audit_log' ) );
209 add_action( 'admin_post_gdpr_data_breach', array( $plugin_admin, 'send_data_breach_confirmation_email' ) );
210 add_action( 'clean_gdpr_data_breach_request', array( $plugin_admin, 'clean_data_breach_request' ), 10, 2 ); // CRON JOB
211 add_action( 'telemetry_cleanup', array( $plugin_admin, 'telemetry_cleanup' ) ); // CRON JOB
212
213 add_action( 'admin_post_gdpr_delete_user', array( $requests_admin, 'delete_user' ) );
214 add_action( 'admin_post_gdpr_cancel_request', array( $requests_admin, 'cancel_request' ) );
215 add_action( 'admin_post_gdpr_add_to_deletion_requests', array( $requests_admin, 'add_to_deletion_requests' ) );
216 add_action( 'admin_post_gdpr_mark_resolved', array( $requests_admin, 'mark_resolved' ) );
217 add_action( 'wp_ajax_gdpr_anonymize_comments', array( $requests_admin, 'anonymize_comments' ) );
218 add_action( 'wp_ajax_gdpr_reassign_content', array( $requests_admin, 'reassign_content' ) );
219
220 add_action( 'init', array( $telemetry, 'register_post_type' ) );
221 add_filter( 'http_api_debug', array( $telemetry, 'log_request' ), 10, 5 );
222 add_filter( 'manage_telemetry_posts_columns', array( $telemetry, 'manage_columns' ) );
223 add_filter( 'manage_telemetry_posts_custom_column', array( $telemetry, 'custom_column' ), 10, 2 );
224 add_filter( 'restrict_manage_posts', array( $telemetry, 'actions_above_table' ) );
225 add_filter( 'views_edit-telemetry', '__return_null' );
226
227 // CRON JOBS
228 add_action( 'clean_gdpr_requests', array( $requests, 'clean_requests' ) );
229 add_action( 'clean_gdpr_user_request_key', array( $requests, 'clean_user_request_key' ), 10, 2 );
230
231 add_action( 'send_data_breach_emails', array( $plugin_emails, 'send_data_breach_emails' ), 10, 2 );
232 }
233
234 /**
235 * Fixes nonce manipulation made by Woocommerce.
236 * @param int $user_id The user id.
237 * @param string $action The nonce Action.
238 * @return int The user id.
239 */
240 function woo_nonce_fix( $user_id, $action ) {
241 if ( ( 0 !== $user_id ) && $action && ( false !== strpos( $action, 'gdpr-' ) ) ) {
242 $user_id = 0;
243 }
244
245 return $user_id;
246 }
247
248 /**
249 * Register all of the hooks related to the public-facing functionality
250 * of the plugin.
251 *
252 * @since 1.0.0
253 * @author Fernando Claussen <fernandoclaussen@gmail.com>
254 * @access private
255 */
256 private function define_public_hooks() {
257
258 $plugin_public = new GDPR_Public( $this->get_plugin_name(), $this->get_version() );
259 $requests_public = new GDPR_Requests_Public( $this->get_plugin_name(), $this->get_version() );
260
261 add_action( 'wp_enqueue_scripts', array( $plugin_public, 'enqueue_styles' ) );
262 add_action( 'wp_enqueue_scripts', array( $plugin_public, 'enqueue_scripts' ) );
263 add_action( 'init', array( $plugin_public, 'set_plugin_cookies' ) );
264 add_action( 'wp_footer', array( $plugin_public, 'overlay' ) );
265 add_action( 'wp_footer', array( $plugin_public, 'privacy_bar' ) );
266 add_action( 'wp_footer', array( $plugin_public, 'is_consent_needed' ) );
267 add_action( 'wp_footer', array( $plugin_public, 'privacy_preferences_modal' ) );
268 add_action( 'wp_footer', array( $plugin_public, 'confirmation_screens' ) );
269 add_action( 'wp_ajax_disagree_with_terms', array( $plugin_public, 'logout' ) );
270 add_action( 'wp_ajax_agree_with_terms', array( $plugin_public, 'agree_with_terms' ) );
271 add_action( 'wp_ajax_gdpr_update_privacy_preferences', array( $plugin_public, 'update_privacy_preferences' ) );
272 add_action( 'wp_ajax_nopriv_gdpr_update_privacy_preferences', array( $plugin_public, 'update_privacy_preferences' ) );
273 add_action( 'wp_ajax_agree_with_new_policies', array( $plugin_public, 'agree_with_new_policies' ) );
274 add_action( 'wp_ajax_nopriv_agree_with_new_policies', array( $plugin_public, 'agree_with_new_policies' ) );
275
276 add_action( 'wp', array( $requests_public, 'request_confirmed' ) );
277 add_action( 'wp_ajax_gdpr_send_request_email', array( $requests_public, 'send_request_email' ) );
278 add_action( 'wp_ajax_nopriv_gdpr_send_request_email', array( $requests_public, 'send_request_email' ) );
279 }
280
281 /**
282 * Checks in an array if a value is found using LIKE instead of =.
283 * @since 1.4.3
284 * @author Fernando Claussen <fernandoclaussen@gmail.com>
285 * @return Bool
286 */
287 public static function similar_in_array( $needle, $haystack ) {
288 foreach ( $haystack as $value ) {
289 if( stripos( strtolower($value) , strtolower($needle) ) !== false ) {
290 return true;
291 }
292 }
293
294 return false;
295 }
296
297 /**
298 * Save the extra fields on a successful registration.
299 * @since 1.0.0
300 * @author Fernando Claussen <fernandoclaussen@gmail.com>
301 * @param int $user_id The user ID.
302 */
303 public static function save_user_consent_on_registration( $user_id ) {
304 GDPR_Audit_Log::log( $user_id, esc_html__( 'User registered to the site.', 'gdpr' ) );
305
306 if ( isset( $_POST['user_consents'] ) ) {
307
308 $consents = array_map( 'sanitize_text_field', array_keys( $_POST['user_consents'] ) );
309 foreach ( $consents as $consent ) {
310 /* translators: Name of consent */
311 GDPR_Audit_Log::log( $user_id, sprintf( esc_html__( 'User gave explicit consent to %s', 'gdpr' ), $consent ) );
312 add_user_meta( $user_id, 'gdpr_consents', $consent );
313 }
314 setcookie( "gdpr[consent_types]", json_encode( $consents ), time() + YEAR_IN_SECONDS, "/" );
315 }
316 }
317
318 /**
319 * Returns the consent checkboxes to be used across the site.
320 * @since 1.2.0
321 * @author Fernando Claussen <fernandoclaussen@gmail.com>
322 */
323 public static function get_consent_checkboxes( $consent_key = false ) {
324 $consent_types = get_option( 'gdpr_consent_types', array() );
325 $sent_extras = ( isset( $_POST['user_consents'] ) ) ? $_POST['user_consents'] : array();
326 $allowed_html = array(
327 'a' => array(
328 'href' => true,
329 'title' => true,
330 'target' => true,
331 ),
332 );
333
334 if ( $consent_key ) {
335 $consent_types = array_filter( $consent_types, function( $key ) use ( $consent_key ) {
336 return $key === $consent_key;
337 }, ARRAY_FILTER_USE_KEY );
338 }
339
340 ob_start();
341 foreach ( $consent_types as $key => $consent ) {
342 $required = ( isset( $consent['policy-page'] ) && $consent['policy-page'] ) ? 'required' : '';
343 $checked = ( isset( $sent_extras[ $key ] ) ) ? checked( $sent_extras[ $key ], 1, false ) : '';
344 echo '<p>' .
345 '<input type="checkbox" name="user_consents[' . esc_attr( $key ) . ']" id="' . esc_attr( $key ) . '-consent" value="1" ' . $required . ' ' . $checked . '>' .
346 '<label for="' . esc_attr( $key ) . '-consent">' . wp_kses( $consent['registration'], $allowed_html ) . '</label>' .
347 '</p>';
348 }
349
350 return ob_get_clean();
351 }
352
353 /**
354 * Renders consent checkboxes to be used across the site.
355 * @since 1.1.4
356 * @author Fernando Claussen <fernandoclaussen@gmail.com>
357 */
358 public static function consent_checkboxes( $consent_key = false ) {
359 echo self::get_consent_checkboxes( $consent_key );
360 }
361
362 /**
363 * Get user meta for exporting.
364 * @since 1.0.0
365 * @author Fernando Claussen <fernandoclaussen@gmail.com>
366 * @static
367 * @param int $user_id The user ID.
368 * @return array The user meta minus not important metas.
369 */
370 static function get_user_meta( $user_id ) {
371 $usermeta = get_user_meta( $user_id );
372 $remove_metadata = array(
373 'nickname',
374 'first_name',
375 'last_name',
376 'description',
377 'rich_editing',
378 'syntax_highlighting',
379 'comment_shortcuts',
380 'admin_color',
381 'use_ssl',
382 'show_admin_bar_front',
383 'wp_capabilities',
384 'wp_user_level',
385 'gdpr_consents',
386 'gdpr_audit_log',
387 'dismissed_wp_pointers',
388 'gdpr_delete_key',
389 'gdpr_rectify_key',
390 'gdpr_complaint_key',
391 'gdpr_export-data_key',
392
393 );
394
395 return array_diff_key( $usermeta, array_flip( $remove_metadata ) );
396 }
397
398 /**
399 * Generates the export in JSON or XML formats.
400 * @since 1.0.0
401 * @author Fernando Claussen <fernandoclaussen@gmail.com>
402 * @static
403 * @param string $email The user email.
404 * @param string $format Either XML or JSON.
405 * @return string Returns the file as string.
406 */
407 static function generate_export( $email, $format ) {
408
409 $email = sanitize_email( $email );
410 $user = get_user_by( 'email', $email );
411
412 if ( ! $user instanceof WP_User ) {
413 return false;
414 }
415
416 $usermeta = self::get_user_meta( $user->ID );
417 $comments = get_comments( array(
418 'author_email' => $user->user_email,
419 'include_unapproved' => true,
420 ) );
421 $user_consents = get_user_meta( $user->ID, 'gdpr_consents' );
422 $extra_content = apply_filters( 'gdpr_export_data_extra_tables', '', $email );
423
424 switch ( strtolower( $format ) ) {
425 case 'json':
426 $metadata = array();
427
428 foreach ( $usermeta as $k => $v ) {
429 $metadata[ $k ] = array();
430 foreach ( $v as $value ) {
431 if ( is_serialized( $value ) ) {
432 $metadata[ $k ][] = maybe_unserialize( $value );
433 } else {
434 $metadata[ $k ] = $value;
435 }
436 }
437 }
438
439 $comments_array = array();
440 if ( ! empty( $comments ) ) {
441 foreach ( $comments as $k => $v ) {
442 $comments_array[ $k ] = array(
443 'comment_author' => $v->comment_author,
444 'comment_author_email' => $v->comment_author_email,
445 'comment_author_url' => $v->comment_author_url,
446 'comment_author_IP' => $v->comment_author_IP,
447 'comment_date' => $v->comment_date,
448 'comment_agent' => $v->comment_agent,
449 'comment_content' => $v->comment_content,
450 );
451 }
452 }
453
454 $json = array(
455 'Personal Information' => array(
456 'Username' => $user->user_login,
457 'First name' => $user->first_name,
458 'Last name' => $user->last_name,
459 'Email' => $user->user_email,
460 'Nickname' => $user->nickname,
461 'Display name' => $user->display_name,
462 'Description' => $user->description,
463 'Website' => $user->user_url,
464 ),
465 'Consents' => $user_consents,
466 'Metadata' => $metadata,
467 'Comments' => $comments_array,
468 );
469
470 if ( $extra_content ) {
471 $json[ $extra_content['name'] ] = $extra_content['content'];
472 }
473 return json_encode( $json );
474 break;
475 case 'md':
476 case 'markdown':
477 # code...
478 break;
479
480 default: // XML
481 $dom = new DomDocument( '1.0', 'ISO-8859-1' );
482 $data_wrapper = $dom->createElement( 'Data' );
483 $dom->appendChild( $data_wrapper );
484 $personal_info = $dom->createElement( 'Personal_Information' );
485 $data_wrapper->appendChild( $personal_info );
486 $personal_info->appendChild( $dom->createElement( 'Username', $user->user_login ) );
487 $personal_info->appendChild( $dom->createElement( 'First_Name', $user->first_name ) );
488 $personal_info->appendChild( $dom->createElement( 'Last_Name', $user->last_name ) );
489 $personal_info->appendChild( $dom->createElement( 'Email', $user->user_email ) );
490 $personal_info->appendChild( $dom->createElement( 'Nickname', $user->nickname ) );
491 $personal_info->appendChild( $dom->createElement( 'Display_Name', $user->display_name ) );
492 $personal_info->appendChild( $dom->createElement( 'Description', $user->description ) );
493 $personal_info->appendChild( $dom->createElement( 'Website', $user->user_url ) );
494
495 if ( ! empty( $user_consents ) ) {
496 $consents = $dom->createElement( 'Consents' );
497 $data_wrapper->appendChild( $consents );
498 foreach ( $user_consents as $consent_item ) {
499 $consents->appendChild( $dom->createElement( 'consent', $consent_item ) );
500 }
501 }
502
503 if ( ! empty( $comments ) ) {
504 $comments_node = $dom->createElement( 'Comments' );
505 $data_wrapper->appendChild( $comments_node );
506 foreach ( $comments as $k => $v ) {
507 $single_comment = $dom->createElement( 'Comment' );
508 $comments_node->appendChild( $single_comment );
509 $single_comment->appendChild( $dom->createElement( 'comment_author', htmlspecialchars( $v->comment_author ) ) );
510 $single_comment->appendChild( $dom->createElement( 'comment_author_email', htmlspecialchars( $v->comment_author_email ) ) );
511 $single_comment->appendChild( $dom->createElement( 'comment_author_url', htmlspecialchars( $v->comment_author_url ) ) );
512 $single_comment->appendChild( $dom->createElement( 'comment_author_IP', htmlspecialchars( $v->comment_author_IP ) ) );
513 $single_comment->appendChild( $dom->createElement( 'comment_date', htmlspecialchars( $v->comment_date ) ) );
514 $single_comment->appendChild( $dom->createElement( 'comment_agent', htmlspecialchars( $v->comment_agent ) ) );
515 $single_comment->appendChild( $dom->createElement( 'comment_content', htmlspecialchars( $v->comment_content ) ) );
516 }
517 }
518
519 $meta_data = $dom->createElement( 'Metadata' );
520 $data_wrapper->appendChild( $meta_data );
521
522 foreach ( $usermeta as $k => $v ) {
523 $k = is_numeric( substr( $k, 0, 1 ) ) ? '_' . $k : $k;
524 $key = $dom->createElement( htmlspecialchars( $k ) );
525 $meta_data->appendChild( $key );
526 foreach ( $v as $value ) {
527 if ( is_serialized( $value ) ) {
528 $value = maybe_unserialize( $value );
529 }
530 $key->appendChild( $dom->createElement( 'item', htmlspecialchars( $value ) ) );
531 }
532 }
533
534 if ( $extra_content ) {
535 $extra = $dom->createElement( $extra_content['name'] );
536 $data_wrapper->appendChild( $extra );
537 foreach ( $extra_content['content'] as $key => $obj ) {
538 $item = $extra->appendChild( $dom->createElement( 'item' ) );
539 foreach ( $obj as $k => $value ) {
540 $item->appendChild( $dom->createElement( $k, ( is_object( $value ) || is_array( $value ) ) ? serialize( (array) $value ) : $value ) );
541 }
542 }
543 }
544
545 $dom->preserveWhiteSpace = false;
546 $dom->formatOutput = true;
547 return $dom->saveXML();
548 break;
549 }
550
551 return false;
552
553 }
554
555 /**
556 * Export the generated export file.
557 * @since 1.0.0
558 * @author Fernando Claussen <fernandoclaussen@gmail.com>
559 */
560 function export_data() {
561 if ( ! isset( $_POST['nonce'], $_POST['email'], $_POST['type'] ) || ! wp_verify_nonce( sanitize_key( wp_unslash( $_POST['nonce'] ) ), 'gdpr-export-data' ) ) {
562 wp_send_json_error();
563 }
564
565 $type = sanitize_text_field( wp_unslash( $_POST['type'] ) );
566 $email = sanitize_email( $_POST['email'] );
567 $user = get_user_by( 'email', $email );
568
569 if ( ! $user instanceof WP_User ) {
570 wp_send_json_error();
571 }
572
573 $export = self::generate_export( $email, $type );
574 if ( $export ) {
575 wp_send_json_success( $export );
576 }
577
578 wp_send_json_error();
579 }
580
581 /**
582 * Save a consent to the user meta.
583 * @since 1.1.4
584 * @author Fernando Claussen <fernandoclaussen@gmail.com>
585 * @param integer $user_id The user ID.
586 * @param string $consent The consent ID.
587 * @return void
588 */
589 public static function save_consent( $user_id, $consent ) {
590 $registered_consent = get_option( 'gdpr_consent_types', array() );
591 $consent_ids = array_keys( $registered_consent );
592 $user = get_user_by( 'ID', $user_id );
593 $consent = sanitize_text_field( wp_unslash( $consent ) );
594
595 if ( $user ) {
596 $user_consent = get_user_meta( $user_id, 'gdpr_consents' );
597 if ( in_array( $consent, $consent_ids ) && ! in_array( $consent, $user_consent ) ) {
598 add_user_meta( $user_id, 'gdpr_consents', $consent );
599 $user_consent[] = $consent;
600 setcookie( "gdpr[consent_types]", json_encode( $user_consent ), time() + YEAR_IN_SECONDS, "/" );
601 return true;
602 }
603 }
604
605 return false;
606 }
607
608 /**
609 * Remove a user consent.
610 * @since 1.1.4
611 * @author Fernando Claussen <fernandoclaussen@gmail.com>
612 * @param integer $user_id The user ID.
613 * @param string $consent The consent ID.
614 * @return void
615 */
616 public static function remove_consent( $user_id, $consent ) {
617 $user = get_user_by( 'ID', $user_id );
618
619 if ( $user ) {
620 $user_consent = get_user_meta( $user_id, 'gdpr_consents' );
621
622 $consent = sanitize_text_field( wp_unslash( $consent ) );
623 $key = array_search( $consent, $user_consent );
624 if ( false !== $key ) {
625 delete_user_meta( $user_id, 'gdpr_consents', $consent );
626 unset( $user_consent[ $key ] );
627 setcookie( "gdpr[consent_types]", json_encode( $user_consent ), time() + YEAR_IN_SECONDS, "/" );
628 return true;
629 }
630 }
631
632 return false;
633 }
634
635
636 /**
637 * Generates a random 6 digit pin.
638 * This pin is necessary to use with the audit log files.
639 *
640 * @since 1.0.0
641 * @author Fernando Claussen <fernandoclaussen@gmail.com>
642 * @static
643 * @param integer $length Number of digits.
644 * @return string Returns the generated pin
645 */
646 public static function generate_pin( $length = 6 ) {
647 $bytes = openssl_random_pseudo_bytes( $length / 2 );
648 return strtoupper( bin2hex( $bytes ) );
649 }
650
651
652 /**
653 * The name of the plugin used to uniquely identify it within the context of
654 * WordPress and to define internationalization functionality.
655 *
656 * @since 1.0.0
657 * @author Fernando Claussen <fernandoclaussen@gmail.com>
658 * @return string The name of the plugin.
659 */
660 public function get_plugin_name() {
661 return $this->plugin_name;
662 }
663
664 /**
665 * Retrieve the version number of the plugin.
666 *
667 * @since 1.0.0
668 * @author Fernando Claussen <fernandoclaussen@gmail.com>
669 * @return string The version number of the plugin.
670 */
671 public function get_version() {
672 return $this->version;
673 }
674
675 }
676