Export Personal Data and Erase Personal Data. An entry belongs * to a person when the first email field of its form holds their address. */ final class Privacy { private const PER_PAGE = 50; /** * Creates the handler. * * @param EntryStore $entries Entries. */ public function __construct( private EntryStore $entries ) {} /** * Hooks the exporter and eraser. */ public function register(): void { add_filter( 'wp_privacy_personal_data_exporters', array( $this, 'add_exporter' ) ); add_filter( 'wp_privacy_personal_data_erasers', array( $this, 'add_eraser' ) ); } /** * Removes the hooks. */ public function unregister(): void { remove_filter( 'wp_privacy_personal_data_exporters', array( $this, 'add_exporter' ) ); remove_filter( 'wp_privacy_personal_data_erasers', array( $this, 'add_eraser' ) ); } /** * Adds the exporter. * * @param mixed $exporters Registered exporters. * @return mixed */ public function add_exporter( $exporters ) { if ( is_array( $exporters ) ) { $exporters['forensix-forms'] = array( 'exporter_friendly_name' => __( 'Forensix form entries', 'forensix-digital' ), 'callback' => array( $this, 'export' ), ); } return $exporters; } /** * Adds the eraser. * * @param mixed $erasers Registered erasers. * @return mixed */ public function add_eraser( $erasers ) { if ( is_array( $erasers ) ) { $erasers['forensix-forms'] = array( 'eraser_friendly_name' => __( 'Forensix form entries', 'forensix-digital' ), 'callback' => array( $this, 'erase' ), ); } return $erasers; } /** * Exports the entries of an address. * * @param string $email Address. * @param int $page Page, from 1. * @return array{data: array>, done: bool} */ public function export( string $email, int $page = 1 ): array { $ids = $this->entries->ids_by_email( $email, $page, self::PER_PAGE ); $data = array(); foreach ( $ids as $id ) { $entry = $this->entries->find( $id ); if ( null === $entry ) { continue; } $items = array(); foreach ( (array) $entry['data'] as $row ) { $items[] = array( 'name' => (string) ( $row['label'] ?? '' ), 'value' => (string) ( $row['value'] ?? '' ), ); } $data[] = array( 'group_id' => 'forensix-form-entries', 'group_label' => __( 'Form entries', 'forensix-digital' ), 'item_id' => 'forensix-entry-' . $id, 'data' => $items, ); } return array( 'data' => $data, 'done' => count( $ids ) < self::PER_PAGE, ); } /** * Erases the entries of an address. * * @param string $email Address. WordPress also passes a page number; it is not needed, because each call erases the first page of what is left. * @return array{items_removed: int, items_retained: int, messages: string[], done: bool} */ public function erase( string $email ): array { $ids = $this->entries->ids_by_email( $email, 1, self::PER_PAGE ); foreach ( $ids as $id ) { $this->entries->delete( $id ); } return array( 'items_removed' => count( $ids ), 'items_retained' => 0, 'messages' => array(), 'done' => count( $ids ) < self::PER_PAGE, ); } }