| 1 |
<?php |
| 2 |
/** |
| 3 |
* A class providing privacy tools for Charitable. |
| 4 |
* |
| 5 |
* @package Charitable/Classes/Charitable_Privacy |
| 6 |
* @author David Bisset |
| 7 |
* @copyright Copyright (c) 2022, WP Charitable LLC |
| 8 |
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License |
| 9 |
* @since 1.6.0 |
| 10 |
* @version 1.6.0 |
| 11 |
*/ |
| 12 |
|
| 13 |
// Exit if accessed directly. |
| 14 |
if ( ! defined( 'ABSPATH' ) ) { |
| 15 |
exit; |
| 16 |
} |
| 17 |
|
| 18 |
if ( ! class_exists( 'Charitable_Privacy' ) ) : |
| 19 |
|
| 20 |
/** |
| 21 |
* Charitable_Privacy |
| 22 |
* |
| 23 |
* @since 1.6.0 |
| 24 |
*/ |
| 25 |
class Charitable_Privacy { |
| 26 |
|
| 27 |
/** |
| 28 |
* User donation fields. |
| 29 |
* |
| 30 |
* @since 1.6.0 |
| 31 |
* |
| 32 |
* @var Charitable_Donation_Field[] |
| 33 |
*/ |
| 34 |
protected $user_donation_fields; |
| 35 |
|
| 36 |
/** |
| 37 |
* Fields that should be retained during the Data Retention Period. |
| 38 |
* |
| 39 |
* @since 1.6.0 |
| 40 |
* |
| 41 |
* @var Charitable_Donation_Field[] |
| 42 |
*/ |
| 43 |
protected $data_retention_fields; |
| 44 |
|
| 45 |
/** |
| 46 |
* Set up class instance. |
| 47 |
* |
| 48 |
* @since 1.6.0 |
| 49 |
*/ |
| 50 |
public function __construct() { |
| 51 |
if ( ! function_exists( 'wp_privacy_anonymize_data' ) ) { |
| 52 |
return; |
| 53 |
} |
| 54 |
|
| 55 |
/* Register our data exporter. */ |
| 56 |
add_filter( 'wp_privacy_personal_data_exporters', array( $this, 'register_exporter' ) ); |
| 57 |
|
| 58 |
/* Register our data eraser. */ |
| 59 |
add_filter( 'wp_privacy_personal_data_erasers', array( $this, 'register_eraser' ) ); |
| 60 |
|
| 61 |
/* Add our privacy policy content. */ |
| 62 |
add_action( 'admin_init', array( $this, 'add_privacy_policy_content' ) ); |
| 63 |
} |
| 64 |
|
| 65 |
/** |
| 66 |
* Return the data to be retained for donations within the Data Retention Period. |
| 67 |
* |
| 68 |
* @since 1.6.0 |
| 69 |
* |
| 70 |
* @return array |
| 71 |
*/ |
| 72 |
public function get_data_retention_fields() { |
| 73 |
if ( ! isset( $this->data_retention_fields ) ) { |
| 74 |
$this->data_retention_fields = charitable_get_option( 'data_retention_fields', array_keys( $this->get_user_donation_fields() ) ); |
| 75 |
} |
| 76 |
|
| 77 |
return $this->data_retention_fields; |
| 78 |
} |
| 79 |
|
| 80 |
/** |
| 81 |
* Return the Data Retention Period. |
| 82 |
* |
| 83 |
* @since 1.6.0 |
| 84 |
* |
| 85 |
* @return int|string |
| 86 |
*/ |
| 87 |
public function get_data_retention_period() { |
| 88 |
return charitable_get_option( 'minimum_data_retention_period', 2 ); |
| 89 |
} |
| 90 |
|
| 91 |
/** |
| 92 |
* Get the user donation fields. |
| 93 |
* |
| 94 |
* @since 1.6.0 |
| 95 |
* |
| 96 |
* @return Charitable_Donation_Field[] |
| 97 |
*/ |
| 98 |
public function get_user_donation_fields() { |
| 99 |
if ( ! isset( $this->user_donation_fields ) ) { |
| 100 |
$this->user_donation_fields = charitable()->donation_fields()->get_data_type_fields( 'user' ); |
| 101 |
} |
| 102 |
|
| 103 |
return $this->user_donation_fields; |
| 104 |
} |
| 105 |
|
| 106 |
/** |
| 107 |
* Return all erasable fields for a particular donation. |
| 108 |
* |
| 109 |
* @since 1.6.0 |
| 110 |
* |
| 111 |
* @param int $donation_id The donation ID. |
| 112 |
* @return Charitable_Donation_Field[] |
| 113 |
*/ |
| 114 |
public function get_erasable_fields_for_donation( $donation_id ) { |
| 115 |
if ( ! $this->is_donation_in_data_retention_period( $donation_id ) ) { |
| 116 |
return $this->get_user_donation_fields(); |
| 117 |
} |
| 118 |
|
| 119 |
return $this->get_erasable_fields_in_data_retention_period(); |
| 120 |
} |
| 121 |
|
| 122 |
/** |
| 123 |
* Checks whether a donation is in the Data Retention Period. |
| 124 |
* |
| 125 |
* @since 1.6.0 |
| 126 |
* |
| 127 |
* @param int $donation_id The donation ID. |
| 128 |
* @return boolean |
| 129 |
*/ |
| 130 |
public function is_donation_in_data_retention_period( $donation_id ) { |
| 131 |
$period = $this->get_data_retention_period(); |
| 132 |
|
| 133 |
if ( '0' == (string) $period ) { |
| 134 |
return false; |
| 135 |
} |
| 136 |
|
| 137 |
if ( 'endless' == $period ) { |
| 138 |
return true; |
| 139 |
} |
| 140 |
|
| 141 |
$diff = (int) abs( time() - strtotime( get_post_field( 'post_date_gmt', $donation_id, 'raw' ) ) ); |
| 142 |
|
| 143 |
return floor( $diff / YEAR_IN_SECONDS ) < $period; |
| 144 |
} |
| 145 |
|
| 146 |
/** |
| 147 |
* Register the data exporter. |
| 148 |
* |
| 149 |
* @since 1.6.0 |
| 150 |
* |
| 151 |
* @param array $exporters The list of exporters. |
| 152 |
* @return array |
| 153 |
*/ |
| 154 |
public function register_exporter( $exporters ) { |
| 155 |
return array_merge( $exporters, array( |
| 156 |
array( |
| 157 |
'exporter_friendly_name' => __( 'Charitable Donor Data', 'charitable' ), |
| 158 |
'callback' => array( $this, 'export_user_data' ), |
| 159 |
), |
| 160 |
) ); |
| 161 |
} |
| 162 |
|
| 163 |
/** |
| 164 |
* Register the data eraser. |
| 165 |
* |
| 166 |
* @since 1.6.0 |
| 167 |
* |
| 168 |
* @param array $erasers The list of registered data erasers. |
| 169 |
* @return array |
| 170 |
*/ |
| 171 |
public function register_eraser( $erasers ) { |
| 172 |
return array_merge( $erasers, array( |
| 173 |
array( |
| 174 |
'eraser_friendly_name' => __( 'Charitable Donor Data Eraser', 'charitable' ), |
| 175 |
'callback' => array( $this, 'erase_user_data' ), |
| 176 |
), |
| 177 |
) ); |
| 178 |
} |
| 179 |
|
| 180 |
/** |
| 181 |
* Add privacy policy content for Charitable. |
| 182 |
* |
| 183 |
* @since 1.6.0 |
| 184 |
* |
| 185 |
* @return void |
| 186 |
*/ |
| 187 |
public function add_privacy_policy_content() { |
| 188 |
if ( ! function_exists( 'wp_add_privacy_policy_content' ) ) { |
| 189 |
return; |
| 190 |
} |
| 191 |
|
| 192 |
/** |
| 193 |
* Filter the Charitable privacy policy content. |
| 194 |
* |
| 195 |
* @since 1.6.0 |
| 196 |
* |
| 197 |
* @param string $content The privacy policy content. |
| 198 |
*/ |
| 199 |
$content = wp_kses_post( apply_filters( 'charitable_privacy_policy_content', wpautop( __( ' |
| 200 |
We collect information about you during the donation process on our website. This information may include, but is not limited to, your name, address, phone number, credit card/payment details and any other details that might be requested from you for the purpose of processing your donations. |
| 201 |
|
| 202 |
Handling this data allows us to: |
| 203 |
|
| 204 |
- Send you important account/donation/service information. |
| 205 |
- Respond to your queries, refund requests or complaints. |
| 206 |
- Process payments and prevent fraudulent transactions. We do this on the basis of our legitimate organizational interests. |
| 207 |
- Set up and administer your account, provide technical and donor support, and to verify your identity. |
| 208 |
|
| 209 |
Additionally, we may also collect the following information: |
| 210 |
|
| 211 |
- Your donor comments if you choose to leave them on our website. |
| 212 |
- Cookies which are essential to keep track of your donation history whilst your session is active. This allows you to access your donation receipt without being a registered, logged in user. |
| 213 |
- Account email/password to allow access to your account, if you have one. |
| 214 |
- If you choose to create an account with us, your name, address, email and phone number, which will be used to populate the donation form for future donations. |
| 215 |
', 'charitable' ) ) ) ); |
| 216 |
|
| 217 |
wp_add_privacy_policy_content( 'Charitable', $content ); |
| 218 |
} |
| 219 |
|
| 220 |
/** |
| 221 |
* Return a user's data. |
| 222 |
* |
| 223 |
* We export the following pieces of data: |
| 224 |
* |
| 225 |
* 1. Registered donor meta. (*_usermeta) |
| 226 |
* 2. Donor profile records. (*_charitable_donors table) |
| 227 |
* 3. Donation donor meta. (*_postmeta) |
| 228 |
* |
| 229 |
* @since 1.6.0 |
| 230 |
* |
| 231 |
* @param string $email The user's email address. |
| 232 |
* @param int $page The page of data to retrieve. |
| 233 |
* @return array |
| 234 |
*/ |
| 235 |
public function export_user_data( $email, $page = 1 ) { |
| 236 |
$export_items = array(); |
| 237 |
|
| 238 |
if ( 1 === $page ) { |
| 239 |
/* 1. Get registered donor meta. */ |
| 240 |
$user = get_user_by( 'email', $email ); |
| 241 |
|
| 242 |
if ( $user instanceof WP_User ) { |
| 243 |
$export_items[] = $this->get_registered_donor_data( $user ); |
| 244 |
} |
| 245 |
} |
| 246 |
|
| 247 |
/* 2. Get donor profile. */ |
| 248 |
$profiles = charitable_get_table( 'donors' )->get_personal_data( $email ); |
| 249 |
|
| 250 |
if ( is_array( $profiles ) && 1 === $page ) { |
| 251 |
$export_items = array_merge( |
| 252 |
$export_items, |
| 253 |
array_map( array( $this, 'get_donor_profile_data' ), $profiles ) |
| 254 |
); |
| 255 |
} |
| 256 |
|
| 257 |
/* If there are no donor profiles, there are no donations; return whatever we have. */ |
| 258 |
if ( empty( $profiles ) ) { |
| 259 |
return array( |
| 260 |
'data' => $export_items, |
| 261 |
'done' => true, |
| 262 |
); |
| 263 |
} |
| 264 |
|
| 265 |
/* 3. Donation donor meta */ |
| 266 |
$user_donation_fields = $this->get_user_donation_fields(); |
| 267 |
|
| 268 |
if ( ! empty( $user_donation_fields ) ) { |
| 269 |
$donor_id = wp_list_pluck( $profiles, 'donor_id' ); |
| 270 |
$donations = charitable_get_table( 'campaign_donations' )->get_distinct_ids( 'donation_id', $donor_id, 'donor_id' ); |
| 271 |
$export_items = array_merge( |
| 272 |
$export_items, |
| 273 |
array_map( array( $this, 'get_personal_donation_meta_data' ), $donations ) |
| 274 |
); |
| 275 |
} |
| 276 |
|
| 277 |
return array( |
| 278 |
'data' => $export_items, |
| 279 |
'done' => true, |
| 280 |
); |
| 281 |
} |
| 282 |
|
| 283 |
/** |
| 284 |
* Remove a user's personal data. |
| 285 |
* |
| 286 |
* @since 1.6.0 |
| 287 |
* |
| 288 |
* @param string $email The user's email address. |
| 289 |
* @param int $page The page of data to retrieve. |
| 290 |
* @return array |
| 291 |
*/ |
| 292 |
public function erase_user_data( $email, $page = 1 ) { |
| 293 |
$this->retained = false; |
| 294 |
$this->removed = false; |
| 295 |
|
| 296 |
/* 1. Remove registered donor meta. */ |
| 297 |
$user = get_user_by( 'email', $email ); |
| 298 |
|
| 299 |
if ( $user instanceof WP_User ) { |
| 300 |
$this->erase_registered_donor_personal_data( $user ); |
| 301 |
} |
| 302 |
|
| 303 |
/* 2. Remove donor profile data. */ |
| 304 |
$profiles = charitable_get_table( 'donors' )->get_personal_data( $email ); |
| 305 |
|
| 306 |
if ( is_array( $profiles ) ) { |
| 307 |
charitable_get_table( 'donors' )->erase_donor_data( wp_list_pluck( $profiles, 'donor_id' ) ); |
| 308 |
|
| 309 |
$this->removed = true; |
| 310 |
} |
| 311 |
|
| 312 |
/* If there are no donor profiles, there are no donations. */ |
| 313 |
if ( empty( $profiles ) ) { |
| 314 |
return array( |
| 315 |
'items_removed' => $this->removed, |
| 316 |
'items_retained' => $this->retained, |
| 317 |
'messages' => array(), |
| 318 |
'done' => true, |
| 319 |
); |
| 320 |
} |
| 321 |
|
| 322 |
/* 3. Donation donor meta */ |
| 323 |
$user_donation_fields = $this->get_user_donation_fields(); |
| 324 |
|
| 325 |
if ( ! empty( $user_donation_fields ) ) { |
| 326 |
$donations = $this->get_donations_from_profiles( $profiles ); |
| 327 |
|
| 328 |
array_walk( $donations, array( $this, 'erase_donation_personal_data' ) ); |
| 329 |
} |
| 330 |
|
| 331 |
return array( |
| 332 |
'items_removed' => $this->removed, |
| 333 |
'items_retained' => $this->retained, |
| 334 |
'messages' => array(), |
| 335 |
'done' => true, |
| 336 |
); |
| 337 |
} |
| 338 |
|
| 339 |
/** |
| 340 |
* Return a registered donor's data. |
| 341 |
* |
| 342 |
* @since 1.6.0 |
| 343 |
* |
| 344 |
* @param WP_User $user An instance of `WP_User`. |
| 345 |
* @return array |
| 346 |
*/ |
| 347 |
public function get_registered_donor_data( $user ) { |
| 348 |
$data = array(); |
| 349 |
$form = new Charitable_Profile_Form; |
| 350 |
$methods = array( |
| 351 |
'get_user_fields', |
| 352 |
'get_address_fields', |
| 353 |
'get_social_fields', |
| 354 |
); |
| 355 |
$key_map = charitable_get_user_mapped_keys(); |
| 356 |
|
| 357 |
foreach ( $methods as $method ) { |
| 358 |
$fields = call_user_func( array( $form, $method ) ); |
| 359 |
|
| 360 |
if ( ! is_array( $fields ) ) { |
| 361 |
continue; |
| 362 |
} |
| 363 |
|
| 364 |
foreach ( $fields as $key => $field ) { |
| 365 |
$key = array_key_exists( $key, $key_map ) ? $key_map[ $key ] : $key; |
| 366 |
|
| 367 |
if ( ! $user->has_prop( $key ) ) { |
| 368 |
continue; |
| 369 |
} |
| 370 |
|
| 371 |
$data[] = array( |
| 372 |
'name' => array_key_exists( 'label', $field ) ? $field['label'] : ucfirst( str_replace( '_', ' ', $key ) ), |
| 373 |
'value' => $user->{$key}, |
| 374 |
); |
| 375 |
} |
| 376 |
} |
| 377 |
|
| 378 |
/** |
| 379 |
* Filter the personal donor meta data for a registered donor. |
| 380 |
* |
| 381 |
* @since 1.6.0 |
| 382 |
* |
| 383 |
* @param array $data Set of personal donor data. |
| 384 |
* @param WP_User $user An instance of `WP_User`. |
| 385 |
*/ |
| 386 |
$data = apply_filters( 'charitable_privacy_export_personal_registered_donor_data', $data, $user ); |
| 387 |
|
| 388 |
return array( |
| 389 |
'item_id' => 'user', |
| 390 |
'group_id' => 'charitable_users', |
| 391 |
'group_label' => __( 'Donor Meta', 'charitable' ), |
| 392 |
'data' => $data, |
| 393 |
); |
| 394 |
} |
| 395 |
|
| 396 |
/** |
| 397 |
* Returns donor profile data for export. |
| 398 |
* |
| 399 |
* @since 1.6.0 |
| 400 |
* |
| 401 |
* @param object $profile The profile record. |
| 402 |
* @return array |
| 403 |
*/ |
| 404 |
protected function get_donor_profile_data( $profile ) { |
| 405 |
/** |
| 406 |
* Filter the personal donor record data. |
| 407 |
* |
| 408 |
* @since 1.6.0 |
| 409 |
* |
| 410 |
* @param array $data Set of personal donor data. |
| 411 |
* @param object $profile The profile record. |
| 412 |
*/ |
| 413 |
$data = apply_filters( 'charitable_privacy_export_personal_donor_profile_data', array( |
| 414 |
array( |
| 415 |
'name' => __( 'First Name', 'charitable' ), |
| 416 |
'value' => $profile->first_name, |
| 417 |
), |
| 418 |
array( |
| 419 |
'name' => __( 'Last Name', 'charitable' ), |
| 420 |
'value' => $profile->last_name, |
| 421 |
), |
| 422 |
array( |
| 423 |
'name' => __( 'Email', 'charitable' ), |
| 424 |
'value' => $profile->email, |
| 425 |
), |
| 426 |
) ); |
| 427 |
|
| 428 |
return array( |
| 429 |
'item_id' => 'donor-' . $profile->donor_id, |
| 430 |
'group_id' => 'charitable_donors', |
| 431 |
'group_label' => __( 'Donor Profiles', 'charitable' ), |
| 432 |
'data' => $data, |
| 433 |
); |
| 434 |
} |
| 435 |
|
| 436 |
/** |
| 437 |
* Return the donor meta stored with a donor's donation records. |
| 438 |
* |
| 439 |
* @since 1.6.0 |
| 440 |
* |
| 441 |
* @param int $donation_id A donation ID. |
| 442 |
* @return array |
| 443 |
*/ |
| 444 |
protected function get_personal_donation_meta_data( $donation_id ) { |
| 445 |
$meta = get_post_meta( $donation_id, 'donor', true ); |
| 446 |
|
| 447 |
if ( ! is_array( $meta ) ) { |
| 448 |
return array(); |
| 449 |
} |
| 450 |
|
| 451 |
$data = array(); |
| 452 |
|
| 453 |
foreach ( $this->get_user_donation_fields() as $field_id => $field ) { |
| 454 |
if ( ! array_key_exists( $field_id, $meta ) ) { |
| 455 |
continue; |
| 456 |
} |
| 457 |
|
| 458 |
$data[] = array( |
| 459 |
'name' => $field->label, |
| 460 |
'value' => $meta[ $field_id ], |
| 461 |
); |
| 462 |
} |
| 463 |
|
| 464 |
/** |
| 465 |
* Filter the personal donation meta data for a particular donation. |
| 466 |
* |
| 467 |
* @since 1.6.0 |
| 468 |
* |
| 469 |
* @param array $data Set of personal donation meta data. |
| 470 |
* @param array $data The donor meta array. |
| 471 |
* @param int $donation_id The donation ID. |
| 472 |
*/ |
| 473 |
$data = apply_filters( 'charitable_privacy_export_personal_donation_meta_data', $data, $meta, $donation_id ); |
| 474 |
|
| 475 |
return array( |
| 476 |
'item_id' => 'donation-' . $donation_id, |
| 477 |
'group_id' => 'charitable_donations', |
| 478 |
'group_label' => __( 'Donation Meta', 'charitable' ), |
| 479 |
'data' => $data, |
| 480 |
); |
| 481 |
} |
| 482 |
|
| 483 |
/** |
| 484 |
* Remove personal data for a registered donor. |
| 485 |
* |
| 486 |
* @since 1.6.0 |
| 487 |
* |
| 488 |
* @param WP_User $user The instance of `WP_User`. |
| 489 |
* @return void |
| 490 |
*/ |
| 491 |
protected function erase_registered_donor_personal_data( WP_User $user ) { |
| 492 |
$form = new Charitable_Profile_Form; |
| 493 |
$methods = array( |
| 494 |
'get_user_fields', |
| 495 |
'get_address_fields', |
| 496 |
'get_social_fields', |
| 497 |
); |
| 498 |
$key_map = charitable_get_user_mapped_keys(); |
| 499 |
|
| 500 |
foreach ( $methods as $method ) { |
| 501 |
$fields = call_user_func( array( $form, $method ) ); |
| 502 |
|
| 503 |
if ( ! is_array( $fields ) ) { |
| 504 |
continue; |
| 505 |
} |
| 506 |
|
| 507 |
foreach ( $fields as $key => $field ) { |
| 508 |
$key = array_key_exists( $key, $key_map ) ? $key_map[ $key ] : $key; |
| 509 |
|
| 510 |
if ( ! $user->has_prop( $key ) ) { |
| 511 |
continue; |
| 512 |
} |
| 513 |
|
| 514 |
/* Get the data type we will use for erasing this particular data field. */ |
| 515 |
$data_type = $this->get_field_data_type( (object) $field ); |
| 516 |
|
| 517 |
/** |
| 518 |
* Filter the placeholder data that will replace the personal data. |
| 519 |
* |
| 520 |
* @since 1.6.0 |
| 521 |
* |
| 522 |
* @param string $data The anonymous data. |
| 523 |
* @param mixed $value The current value of the field. |
| 524 |
* @param string $key The key of the field. |
| 525 |
* @param array $field The field definition. |
| 526 |
*/ |
| 527 |
$data = apply_filters( 'charitable_privacy_erasure_registered_user_data_prop_value', wp_privacy_anonymize_data( $data_type, $user->{$key} ), $user->{$key}, $key, $field ); |
| 528 |
|
| 529 |
update_user_meta( $user->ID, $key, $data ); |
| 530 |
|
| 531 |
$this->removed = true; |
| 532 |
} |
| 533 |
} |
| 534 |
} |
| 535 |
|
| 536 |
/** |
| 537 |
* Remove personal data from a single donation. |
| 538 |
* |
| 539 |
* @since 1.6.0 |
| 540 |
* |
| 541 |
* @param int $donation_id The donation ID. |
| 542 |
* @return void |
| 543 |
*/ |
| 544 |
protected function erase_donation_personal_data( $donation_id ) { |
| 545 |
$meta = get_post_meta( $donation_id, 'donor', true ); |
| 546 |
|
| 547 |
foreach ( $this->get_erasable_fields_for_donation( $donation_id ) as $field_id => $field ) { |
| 548 |
if ( ! array_key_exists( $field_id, $meta ) ) { |
| 549 |
continue; |
| 550 |
} |
| 551 |
|
| 552 |
/* Get the data type we will use for erasing this particular data field. */ |
| 553 |
$data_type = $this->get_field_data_type( $field ); |
| 554 |
$replace = empty( $meta[ $field_id ] ) ? '' : wp_privacy_anonymize_data( $data_type, $meta[ $field_id ] ); |
| 555 |
|
| 556 |
/** |
| 557 |
* Filter the placeholder data that will replace the personal data. |
| 558 |
* |
| 559 |
* @since 1.6.0 |
| 560 |
* |
| 561 |
* @param string $data The anonymous data. |
| 562 |
* @param mixed $value The current value of the field. |
| 563 |
* @param string $key The key of the field. |
| 564 |
* @param Charitable_Donation_Field $field The field definition. |
| 565 |
*/ |
| 566 |
$meta[ $field_id ] = apply_filters( 'charitable_privacy_erasure_donation_donor_data_prop_value', $replace, $meta[ $field_id ], $field_id, $field ); |
| 567 |
} |
| 568 |
|
| 569 |
update_post_meta( $donation_id, 'donor', $meta ); |
| 570 |
update_post_meta( $donation_id, 'data_erased', current_time( 'mysql', 0 ) ); |
| 571 |
|
| 572 |
/* Change the post_title since that otherwise has the donor's name. */ |
| 573 |
wp_update_post( array( |
| 574 |
'ID' => $donation_id, |
| 575 |
'post_title' => sprintf( |
| 576 |
/* translators: %s: campaign names */ |
| 577 |
__( 'Anonymous – %s', 'charitable' ), |
| 578 |
charitable_get_donation( $donation_id )->get_campaigns_donated_to() |
| 579 |
), |
| 580 |
) ); |
| 581 |
|
| 582 |
$log = new Charitable_Donation_Log( $donation_id ); |
| 583 |
$log->add( __( 'Personal data erased.', 'charitable' ) ); |
| 584 |
} |
| 585 |
|
| 586 |
/** |
| 587 |
* Checks whether there are any user donation fields that can be erased |
| 588 |
* for donations within the data retention period. |
| 589 |
* |
| 590 |
* @since 1.6.0 |
| 591 |
* |
| 592 |
* @return boolean |
| 593 |
*/ |
| 594 |
protected function has_erasable_fields_within_data_retention_period() { |
| 595 |
return 0 < count( array_unique( |
| 596 |
array_keys( $this->get_user_donation_fields() ), |
| 597 |
$this->get_data_retention_fields() |
| 598 |
) ); |
| 599 |
} |
| 600 |
|
| 601 |
/** |
| 602 |
* Returns the erasable fields within the Data Retention Period. |
| 603 |
* |
| 604 |
* @since 1.6.0 |
| 605 |
* |
| 606 |
* @return Charitable_Donation_Field[] |
| 607 |
*/ |
| 608 |
protected function get_erasable_fields_in_data_retention_period() { |
| 609 |
return array_diff_key( |
| 610 |
$this->get_user_donation_fields(), |
| 611 |
array_flip( $this->get_data_retention_fields() ) |
| 612 |
); |
| 613 |
} |
| 614 |
|
| 615 |
/** |
| 616 |
* Return the donation IDs for one or more profiles. |
| 617 |
* |
| 618 |
* @since 1.6.0 |
| 619 |
* |
| 620 |
* @param object[] $profiles The donor profiles. |
| 621 |
* @return int[] |
| 622 |
*/ |
| 623 |
protected function get_donations_from_profiles( $profiles ) { |
| 624 |
$donor_id = wp_list_pluck( $profiles, 'donor_id' ); |
| 625 |
|
| 626 |
return charitable_get_table( 'campaign_donations' )->get_distinct_ids( 'donation_id', $donor_id, 'donor_id' ); |
| 627 |
} |
| 628 |
|
| 629 |
/** |
| 630 |
* Return the data type for a field. |
| 631 |
* |
| 632 |
* @since 1.6.0 |
| 633 |
* |
| 634 |
* @param object $field The field attributes. This may be a Charitable_Donation_Field |
| 635 |
* instance, or a simple object cast from an array. |
| 636 |
* @return string |
| 637 |
*/ |
| 638 |
protected function get_field_data_type( $field ) { |
| 639 |
if ( isset( $field->type ) ) { |
| 640 |
$type = $field->type; |
| 641 |
} else { |
| 642 |
$type = is_array( $field->donation_form ) ? $field->donation_form['type'] : $field->admin_form['type']; |
| 643 |
} |
| 644 |
|
| 645 |
switch ( $type ) { |
| 646 |
case 'select': |
| 647 |
case 'multi-checkbox': |
| 648 |
$data_type = ''; |
| 649 |
break; |
| 650 |
|
| 651 |
case 'textarea': |
| 652 |
case 'editor': |
| 653 |
$data_type = 'longtext'; |
| 654 |
break; |
| 655 |
|
| 656 |
default: |
| 657 |
$data_type = $type; |
| 658 |
} |
| 659 |
|
| 660 |
/** |
| 661 |
* Filter the data type to use for a field to be erased. |
| 662 |
* |
| 663 |
* @since 1.6.0 |
| 664 |
* |
| 665 |
* @param string $data_type The data type. |
| 666 |
* @param object $field The field attributes. This may be a Charitable_Donation_Field |
| 667 |
* instance, or a simple object cast from an array. |
| 668 |
*/ |
| 669 |
return apply_filters( 'charitable_privacy_erasure_field_data_type', $data_type, $field ); |
| 670 |
} |
| 671 |
} |
| 672 |
|
| 673 |
endif; |
| 674 |
|