| 4338 | $email_address = sanitize_text_field( $_POST['email'] ); |
| 4339 | $processor_index = (int) $_POST['exporter']; |
| 4340 | $page = (int) $_POST['page']; |
| 4341 | |
| 4342 | wp_privacy_do_personal_data_callback( 'export', $processor_index, $email_address, $page ); |
| 4343 | } |
| 4344 | |
| 4345 | /** |
| 4346 | * Ajax handler for erasing a page of personal data. |
| 4347 | * |
| 4348 | * @since 4.9.5 |
| 4349 | */ |
| 4350 | function wp_ajax_wp_privacy_erase_personal_data() { |
| 4351 | check_ajax_referer( 'wp-privacy-erase-personal-data', 'security' ); |
| 4352 | |
| 4353 | $email_address = sanitize_text_field( $_POST['email'] ); |
| 4354 | $processor_index = (int) $_POST['eraser']; |
| 4355 | $page = (int) $_POST['page']; |
| 4356 | |
| 4357 | wp_privacy_do_personal_data_callback( 'erase', $processor_index, $email_address, $page ); |
| 4358 | } |
| 4359 | |
| 4360 | /** |
| 4361 | * Handler for exporting or erasing a page of personal data. |
| 4362 | * |
| 4363 | * @since 4.9.5 |
| 4364 | * |
| 4365 | * @param string $type The type of processing requested: "export" or "erase" |
| 4366 | * @param int $processor_index The index of the processor that should be called. |
| 4367 | * @param string $email_address The email address for which processing is being performed. |
| 4368 | * @param int $page The 1-based page of data to be processed. |
| 4369 | */ |
| 4370 | |
| 4371 | function wp_privacy_do_personal_data_callback( $type, $processor_index, $email_address, $page ) { |
4341 | | /** |
4342 | | * Filters the array of exporter callbacks. |
4343 | | * |
4344 | | * @since 4.9.5. |
4345 | | * |
4346 | | * @param array $args { |
4347 | | * An array of callable exporters of personal data. Default empty array. |
4348 | | * [ |
4349 | | * callback string Callable exporter that accepts an email address and |
4350 | | * a page and returns an array of name => value |
4351 | | * pairs of personal data |
4352 | | * exporter_friendly_name string Translated user facing friendly name for the exporter |
4353 | | * ] |
4354 | | * } |
4355 | | */ |
4356 | | $exporters = apply_filters( 'wp_privacy_personal_data_exporters', array() ); |
| 4378 | if ( ! in_array( $type, $allowed_types ) ) { |
| 4379 | wp_send_json_error( 'invalid processor type' ); |
| 4380 | } |
4358 | | if ( ! is_array( $exporters ) ) { |
4359 | | wp_send_json_error( 'An exporter has improperly used the registration filter.' ); |
| 4382 | $processors = array(); |
| 4383 | if ( 'export' === $type ) { |
| 4384 | /** |
| 4385 | * Filters the array of exporter callbacks. |
| 4386 | * |
| 4387 | * @since 4.9.5. |
| 4388 | * |
| 4389 | * @param array $args { |
| 4390 | * An array of callable exporters of personal data. Default empty array. |
| 4391 | * [ |
| 4392 | * callback string Callable exporter that accepts an email address and |
| 4393 | * a page and returns an array of personal data |
| 4394 | * exporter_friendly_name string Translated user facing friendly name for the exporter |
| 4395 | * ] |
| 4396 | * } |
| 4397 | */ |
| 4398 | $processors = apply_filters( 'wp_privacy_personal_data_exporters', $processors ); |
| 4399 | } else if ( 'erase' === $type ) { |
| 4400 | /** |
| 4401 | * Filters the array of eraser callbacks. |
| 4402 | * |
| 4403 | * @since 4.9.5. |
| 4404 | * |
| 4405 | * @param array $args { |
| 4406 | * An array of callable erasers of personal data. Default empty array. |
| 4407 | * [ |
| 4408 | * callback string Callable eraser that accepts an email address and page |
| 4409 | * eraser_friendly_name string Translated user facing friendly name for the eraser |
| 4410 | * ] |
| 4411 | * } |
| 4412 | */ |
| 4413 | $processors = apply_filters( 'wp_privacy_personal_data_erasers', $processors ); |
4385 | | $exporter = $exporters[ $index ]; |
4386 | | if ( ! is_array( $exporter ) ) { |
4387 | | wp_send_json_error( "Expected an array describing the exporter at index {$exporter_index}." ); |
4388 | | } |
4389 | | if ( ! array_key_exists( 'callback', $exporter ) ) { |
4390 | | wp_send_json_error( "Exporter array at index {$exporter_index} does not include a callback." ); |
4391 | | } |
4392 | | if ( ! is_callable( $exporter['callback'] ) ) { |
4393 | | wp_send_json_error( "Exporter callback at index {$exporter_index} is not a valid callback." ); |
4394 | | } |
4395 | | if ( ! array_key_exists( 'exporter_friendly_name', $exporter ) ) { |
4396 | | wp_send_json_error( "Exporter array at index {$exporter_index} does not include a friendly name." ); |
4397 | | } |
| 4446 | if ( ! is_email( $email_address ) ) { |
| 4447 | wp_send_json_error( 'A valid email address must be given.' ); |
| 4448 | } |
4399 | | $callback = $exporters[ $index ]['callback']; |
4400 | | $exporter_friendly_name = $exporters[ $index ]['exporter_friendly_name']; |
| 4450 | $processor = $processors[ $processor_index - 1 ]; |
| 4451 | if ( ! is_array( $processor ) ) { |
| 4452 | wp_send_json_error( "Expected an array describing the processor at index {$processor_index}." ); |
| 4453 | } |
| 4454 | if ( ! array_key_exists( 'callback', $processor ) ) { |
| 4455 | wp_send_json_error( "Processor array at index {$processor_index} does not include a callback." ); |
| 4456 | } |
| 4457 | if ( ! is_callable( $processor['callback'] ) ) { |
| 4458 | wp_send_json_error( "Processor callback at index {$processor_index} is not a valid callback." ); |
| 4459 | } |
4407 | | if ( ! is_array( $response ) ) { |
4408 | | wp_send_json_error( "Expected response as an array from exporter: {$exporter_friendly_name}." ); |
| 4466 | if ( 'export' === $type ) { |
| 4467 | $processor_friendly_name = __( 'Unnamed exporter' ); |
| 4468 | } else if ( 'erase' === $type ) { |
| 4469 | $processor_friendly_name = __( 'Unnamed eraser' ); |
| 4470 | } |
| 4471 | |
| 4472 | if ( array_key_exists( 'friendly_name', $processor ) ) { |
| 4473 | if ( ! empty( $processor['friendly_name'] ) ) { |
| 4474 | $processor_friendly_name = $processor['friendly_name']; |
4410 | | if ( ! array_key_exists( 'data', $response ) ) { |
4411 | | wp_send_json_error( "Expected data in response array from exporter: {$exporter_friendly_name}." ); |
4412 | | } |
4413 | | if ( ! is_array( $response['data'] ) ) { |
4414 | | wp_send_json_error( "Expected data array in response array from exporter: {$exporter_friendly_name}." ); |
4415 | | } |
4416 | | if ( ! array_key_exists( 'done', $response ) ) { |
4417 | | wp_send_json_error( "Expected done (boolean) in response array from exporter: {$exporter_friendly_name}." ); |
4418 | | } |
4419 | | } else { |
4420 | | // No exporters, so we're done |
4421 | | $response = array( |
4422 | | 'data' => array(), |
4423 | | 'done' => true, |
4424 | | ); |
4427 | | /** |
4428 | | * Filters a page of personal data exporter data. Used to build the export report. |
4429 | | * |
4430 | | * Allows the export response to be consumed by destinations in addition to Ajax. |
4431 | | * |
4432 | | * @since 4.9.5 |
4433 | | * |
4434 | | * @param array $response The personal data for the given exporter and page. |
4435 | | * @param int $exporter_index The index of the exporter that provided this data. |
4436 | | * @param string $email_address The email address associated with this personal data. |
4437 | | * @param int $page The zero-based page for this response. |
4438 | | */ |
4439 | | $response = apply_filters( 'wp_privacy_personal_data_export_page', $response, $exporter_index, $email_address, $page ); |
| 4478 | if ( ! is_array( $response ) ) { |
| 4479 | wp_send_json_error( "Expected response as an array from {$processor_friendly_name}." ); |
| 4480 | } |
| 4481 | if ( ! array_key_exists( 'data', $response ) ) { |
| 4482 | wp_send_json_error( "Expected data in response array from {$processor_friendly_name}." ); |
| 4483 | } |
| 4484 | if ( ! is_array( $response['data'] ) ) { |
| 4485 | wp_send_json_error( "Expected data array in response array from {$processor_friendly_name}." ); |
| 4486 | } |
| 4487 | if ( ! array_key_exists( 'done', $response ) ) { |
| 4488 | wp_send_json_error( "Expected done (boolean) in response array from {$processor_friendly_name}." ); |
| 4489 | } |
| 4490 | |
| 4491 | // If we're doing an export, run the export filter (for things like export file assembly) |
| 4492 | if ( 'export' === $type ) { |
| 4493 | /** |
| 4494 | * Filters a page of personal data exporter data. Used to build the export report. |
| 4495 | * |
| 4496 | * Allows the export response to be consumed by destinations in addition to Ajax. |
| 4497 | * |
| 4498 | * @since 4.9.5 |
| 4499 | * |
| 4500 | * @param array $response The personal data for the given exporter and page. |
| 4501 | * @param int $processor_index The index of the exporter that provided this data. |
| 4502 | * @param string $email_address The email address associated with this personal data. |
| 4503 | * @param int $page The 1-based page for this response. |
| 4504 | */ |
| 4505 | $response = apply_filters( 'wp_privacy_personal_data_export_page', $response, $processor_index, $email_address, $page ); |
| 4506 | } |
| 4507 | |
| 4508 | // And lastly, send our response |