| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448 |
- <?php if ( ! defined( 'ABSPATH' ) ) exit;
- class NF_Admin_UserDataRequests {
- /**
- * @var array
- */
- protected $ignored_field_types = array (
- 'html',
- 'submit',
- 'hr',
- 'recaptcha',
- 'spam',
- 'creditcard',
- 'creditcardcvc',
- 'creditcardexpiration',
- 'creditcardfullname',
- 'creditcardnumber',
- 'creditcardzip'
- );
- /**
- * @var WP_User
- */
- protected $user;
- /**
- * @var string
- */
- protected $request_email;
- /** Class constructor */
- public function __construct() {
- add_filter( 'wp_privacy_personal_data_exporters', array(
- $this, 'plugin_register_exporters' ) );
- add_filter( 'wp_privacy_personal_data_erasers', array(
- $this, 'plugin_register_erasers' ) );
- }
- /**
- * Register exporter for Plugin user data.
- *
- * @param array $exporters
- *
- * @return array
- */
- function plugin_register_exporters( $exporters = array() ) {
- $exporters[] = array(
- 'exporter_friendly_name' => __( 'Ninja Forms Submission Data', 'ninja-forms' ),
- 'callback' => array( $this, 'plugin_user_data_exporter' ),
- );
- return $exporters;
- }
- /**
- * Register eraser for Plugin user data.
- *
- * @param array $erasers
- *
- * @return array
- */
- function plugin_register_erasers( $erasers = array() ) {
- $erasers[] = array(
- 'eraser_friendly_name' => __( 'Ninja Forms Submissions Data', 'ninja-forms' ),
- 'callback' => array( $this, 'plugin_user_data_eraser' ),
- );
- return $erasers;
- }
- /**
- * Adds Ninja Forms Submission data to the default HTML export file that
- * WordPress creates on converted request
- *
- * @param $email_address
- * @param int $page
- *
- * @return array
- */
- function plugin_user_data_exporter( $email_address, $page = 1 ) {
- $export_items = array();
- // get the user
- $this->user = get_user_by( 'email', $email_address );
- $this->request_email = $email_address;
- if( $this->user && $this->user->ID ) {
- $item_id = "ninja-forms-" . $this->user->ID;
- } else {
- $item_id = "ninja-forms";
- }
- $group_id = 'ninja-forms';
- $group_label = __( 'Ninja Forms Submission Data', 'ninja-forms' );
- $subs = $this->get_related_subs( $email_address );
- foreach($subs as $sub) {
- $data = array();
- // get the field values from postmeta
- $sub_meta = get_post_meta( $sub->ID );
- // make sure we have a form submission
- if ( isset( $sub_meta[ '_form_id' ] ) ) {
- $form = Ninja_Forms()->form( $sub_meta[ '_form_id' ][ 0 ] )
- ->get();
- $fields = Ninja_Forms()->form( $sub_meta[ '_form_id' ][ 0 ] )
- ->get_fields();
- foreach ( $fields as $field_id => $field ) {
- // we don't care about submit, hr, divider, html fields
- if ( ! in_array( $field->get_setting( 'type' ),
- $this->ignored_field_types ) ) {
- // make sure there is a value
- if ( isset( $sub_meta[ '_field_' . $field_id ] ) ) {
- //multi-value fields may need to be unserialized
- if( in_array( $field->get_setting( 'type' ),
- array( 'listcheckbox', 'listmultiselect' ) ) ){
- //implode the unserialized array
- $value = implode( ',', maybe_unserialize(
- $sub_meta[ '_field_' . $field_id ][ 0 ] ) );
- } else {
- $value = $sub_meta[ '_field_' . $field_id ][ 0 ];
- }
- // Add label/value pairs to data array
- $data[] = array(
- 'name' => $field->get_setting( 'label' ),
- 'value' => $value
- );
- }
- }
- }
- // Add this group of items to the exporters data array.
- $export_items[] = array(
- 'group_id' => $group_id . '-' . $sub->ID,
- 'group_label' => $group_label . '-' .
- $form->get_setting( 'title' ),
- 'item_id' => $item_id . '-' . $sub->ID,
- 'data' => $data,
- );
- }
- }
- // Returns an array of exported items for this pass, but also a boolean whether this exporter is finished.
- //If not it will be called again with $page increased by 1.
- return array(
- 'data' => $export_items,
- 'done' => true,
- );
- }
- /**
- * Eraser for Plugin user data. This will completely erase all Ninja Form
- * submission data for the user when converted by the admin.
- *
- * @param $email_address
- * @param int $page
- *
- * @return array
- */
- function plugin_user_data_eraser( $email_address, $page = 1 ) {
- if ( empty( $email_address ) ) {
- return array(
- 'items_removed' => false,
- 'items_retained' => false,
- 'messages' => array(),
- 'done' => true,
- );
- }
- // get the user
- $this->user = get_user_by( 'email', $email_address );
- $this->request_email = $email_address;
- $request_id = $_REQUEST[ 'id' ];
- $make_anonymous = get_post_meta( $request_id, 'nf_anonymize_data',
- true);
- $messages = array();
- $items_removed = false;
- $items_retained = false;
- $subs = $this->get_related_subs( $email_address );
- if( 0 < sizeof( $subs ) ) {
- $items_removed = true;
- }
- if( '1' != $make_anonymous ) {
- $this->delete_submissions( $subs );
- $items_removed = true;
- } else {
- $this->anonymize_submissions( $subs, $email_address );
- }
- /**
- * Returns an array of exported items for this pass, but also a boolean
- * whether this exporter is finished.
- * If not it will be called again with $page increased by 1.
- * */
- return array(
- 'items_removed' => $items_removed,
- 'items_retained' => $items_retained,
- 'messages' => $messages,
- 'done' => true,
- );
- }
- /**
- * Retrieve all submissions related(by author id or email address) to the
- * given email address
- *
- * @param $email_address
- *
- * @return array
- */
- private function get_related_subs( $email_address ) {
- // array if subs where user is author
- $logged_in_subs = array();
- if ( $this->user && $this->user->ID ) {
- // get submission ids the old-fashioned way if user is author
- $logged_in_subs = get_posts(
- array(
- 'author' => $this->user->ID,
- 'post_type' => 'nf_sub',
- 'posts_per_page' => - 1,
- 'fields' => 'ids'
- )
- );
- }
- // get submission ids where email address is a field value
- $anon_sub_ids = $this->get_subs_by_email( $email_address );
- // merge anonymous and author submissions ids and get unique
- $sub_ids = array_unique( array_merge( $logged_in_subs, $anon_sub_ids ) );
- // return empty array if $sub_ids is empty
- if( 1 > count( $sub_ids ) ) {
- return array();
- }
- // get post objects related to the email address
- return get_posts(
- array(
- 'include' => implode(',', $sub_ids),
- 'post_type' => 'nf_sub',
- 'posts_per_page' => -1,
- )
- );
- }
- /**
- * Get submission ids where the submission has the give email address as
- * data
- *
- * @param $email_address
- *
- * @return array
- */
- private function get_subs_by_email( $email_address ) {
- global $wpdb;
- // query to find any submission with our requester's email as value
- $anon_subs_query = "SELECT DISTINCT(m.post_id) FROM `" . $wpdb->prefix
- . "postmeta` m
- JOIN `" . $wpdb->prefix . "posts` p ON p.id = m.post_id
- WHERE m.meta_value = '" . $email_address . "'
- AND p.post_type = 'nf_sub'";
- $anon_subs = $wpdb->get_results( $anon_subs_query );
- $sub_id_array = array();
- // let's get the integer value of those submission ids
- if( 0 < sizeof( $anon_subs ) ) {
- foreach( $anon_subs as $sub ) {
- $sub_id_array[] = intval( $sub->post_id );
- }
- }
- return $sub_id_array;
- }
- /**
- * Delete Submissions
- *
- * @param $subs
- */
- private function delete_submissions( $subs ) {
- if( 0 < sizeof( $subs ) ) {
- // iterate and delete the submissions
- foreach($subs as $sub) {
- wp_delete_post( $sub->ID, true );
- }
- }
- }
- /**
- * This will (redact) personal data and anonymize submissions
- *
- * @param $subs
- */
- private function anonymize_submissions( $subs ) {
- $form_id_array = array();
- $submitter_field = '';
- if( 0 < sizeof( $subs ) ) {
- $anonymize_data = false;
- foreach( $subs as $sub ) {
- // get the form id
- $form_id = get_post_meta( $sub->ID, '_form_id', true );
- $form = Ninja_Forms()->form( $form_id );
- /*
- * Do we have a use, if so does the post(submission) author
- * match the user. If so, then anonymize
- */
- if( $this->user && $this->user->ID
- && $sub->post_author == $this->user->ID ) {
- $anonymize_data = true;
- } else {
- /*
- * Otherwise, does the submitter email for the submission
- * equal the email for the request
- */
- $form_submitter_email = '';
- if( in_array( $form_id, array_keys( $form_id_array ) ) ) {
- /*
- * if we already have the submitter field key, no
- * need to iterate over the actions again
- */
- $submitter_field = $form_id_array[ $form_id ];
- } else {
- $actions = $form->get_actions();
- if ( 0 < sizeof( $actions ) ) {
- foreach ( $actions as $action ) {
- // we only care about the save action
- if ( 'save' == $action->get_setting( 'type' )
- && null != $action->get_setting( 'submitter_email' )
- && '' != $action->get_setting( 'submitter_email' ) ) {
- // get the submitter field
- $submitter_field = $action->get_setting( 'submitter_email' );
- /*
- * Add the form id and submitter field to
- * this array so we don't have to load
- * the form again if we have multiple
- * submissions for the same form
- */
- $form_id_array[ $form_id ] = $submitter_field;
- break;
- }
- }
- }
- }
- /*
- * If the submitter field is not empty, then let's
- * get the value given in the form submission for
- * that field
- */
- if ( '' != $submitter_field ) {
- $fields = $form->get_fields();
- foreach ( $fields as $field ) {
- $key = $field->get_setting( 'key' );
- // we only care about email fields
- if ( 'email' == $field->get_setting( 'type' )
- && $submitter_field == $key ) {
- // if we have a match, get the value
- $form_submitter_email = get_post_meta(
- $sub->ID,
- '_field_' . $field->get_id(),
- true );
- break;
- }
- }
- }
- // if form submitter email matches requester's email
- if( $form_submitter_email === $this->request_email ) {
- $anonymize_data = true;
- }
- }
- if( $anonymize_data ) {
- // anonymize the actual submitted for values
- $this->anonymize_fields($sub, $form->get_fields() );
- }
- }
- }
- }
- /**
- * This will anonymize personally identifiable fields and anonymize
- * submissions submitted by the user with the provided email address
- *
- * @param $sub
- * @param $fields
- */
- private function anonymize_fields( $sub, $fields ) {
- foreach( $fields as $field ) {
- $type = $field->get_setting( 'type' );
- // ignore fields that aren't saved
- if( ! in_array( $type, $this->ignored_field_types ) ) {
- $is_personal = $field->get_setting( 'personally_identifiable' );
- /**
- * If this is personally identifiable, redact it
- */
- if( null != $is_personal && '1' == $is_personal ) {
- $field_id = $field->get_id();
- // make sure we have that field saved.
- $field_value = get_post_meta(
- $sub->ID,
- '_field_' . $field_id,
- true
- );
- if( '' != $field_value ) {
- update_post_meta(
- $sub->ID,
- '_field_' . $field_id,
- '(redacted)'
- );
- }
- }
- }
- }
- // Remove the author id if the the email address belongs to the author
- if( $this->user && $this->user->ID &&
- $this->user->ID == $sub->post_author ) {
- wp_update_post(
- array(
- 'ID' => $sub->ID,
- 'post_author' => 0
- )
- );
- }
- }
- }
|