Make WordPress Core

Ticket #43602:

File, 5.7 KB (added by allendav, 6 years ago)

Removes ZIP reference (copy and paste error), gives guidance on how plugins can control erasure, fixes 0 in example response to boolean false to match new response shape

1# How to Connect Your Plugin to Core's New Personal Data Eraser
3## Background
5In WordPress 4.9.x, new tools were added to make compliance easier with laws
6like the European Union's General Data Protection Regulation, or GDPR for
7short. Among the tools added is a Personal Data Removal tool which supports
8erasing/anonymizing personal data for a given user. It does NOT delete
9registered user accounts - that is still a separate step the admin can
10choose whether or not to do.
12In addition to the personal data stored in things like WordPress comments,
13plugins can also hook into the eraser feature to erase the personal
14data they collect, whether it be in something like postmeta or even an
15entirely new Custom Post Type (CPT).
17## How It Works
19Like the exporters, the "key" for all the erasers is the user's email address -
20this was chosen because it supports erasing personal data for both full-fledged
21registered users and also unregistered users (e.g. like a logged out commenter).
23However, since performing a personal data erase is a destructive process, we
24don't want to just do it without confirming the request, so the admin-facing
25UX starts all requests by having the admin enter the username or email address
26making the request and then sends then a link to click to confirm their
29A list of requests and whether they have been confirmed is available to
30the administrator in the same user interface.  Once a request has been
31confirmed, the admin can kick off personal data erasure for the user.
33## Design Internals
35The way the personal data export is erased is similar to how the personal data
36exporters - and relies on hooking "eraser" callbacks to do the dirty work
37of erasing the data.
39When the admin clicks on the remove personal data link, an AJAX loop begins
40that iterates over all the erasers registered in the system, one at a time.
41In addition to erasers built into core, plugins can register their own
42eraser callbacks.
44The eraser callback interface is designed to be as simple as possible.
45An eraser callback receives the email address we are working with,
46and a page parameter as well. The page parameter (which starts at 1) is
47used to avoid plugins potentially causing timeouts by attempting to erase
48all the personal data they've collected at once.
50The eraser callback replies whether items containing personal data were
51erased, whether any items containing personal data were retained, an
52array of messages to present to the admin (explaining why items that were
53retained were retained) and whether it is done or not. If an eraser
54callback reports that it is not done, it will be called again (in a
55separate request) with the page parameter incremented by 1.
57When all the exporters have been called to completion, the UX is updated to
58show whether or not all personal data found was erased, and any messages
59explaining why personal data was retained.
61A good example is a plugin that takes e-commerce orders. The plugin's settings
62could say that personal data should be retained for orders < XXX days old. The
63plugin's order eraser could look at that setting against each order
64and decide whether or not to remove it. If it decides not to remove it,
65it can emit a message in the AJAX to say as much to the admin (i.e. Order
661234 was not erased because it is less than XXX days old.)
68The intention for now is that plugins may choose to expose erasure controls
69in their own settings user interfaces where it makes the most contextual sense.
71## What to Do
73A plugin can register one or more erasers, but most plugins will only
74need one. Let's work on a hypothetical plugin which adds commenter location
75data to comments.
77Let's assume the plugin has used `add_comment_meta` to add location
78data using `meta_key`s of `latitude` and `longitude`
80The first thing the plugin needs to do is to create an eraser function
81that accepts an email address and a page, e.g.:
84function my_plugin_eraser( $email_address, $page = 1 ) {
85  $number = 500; // Limit us to avoid timing out
86  $page = (int) $page;
88  $export_items = array();
90  $comments = get_comments(
91    array(
92      'author_email' => $email_address,
93      'number'       => $number,
94      'paged'        => $page,
95      'order_by'     => 'comment_ID',
96      'order'        => 'ASC',
97      )
98  );
100  $items_removed = false;
102  foreach ( (array) $comments as $comment ) {
103    $latitude  = get_comment_meta( $comment->comment_ID, 'latitude', true );
104    $longitude = get_comment_meta( $comment->comment_ID, 'longitude', true );
106    if ( ! empty( $latitude ) ) {
107      delete_comment_meta( $comment->comment_ID, 'latitude' );
108      $items_removed = true;
109    }
111    if ( ! empty( $longitude ) ) {
112      delete_comment_meta( $comment->comment_ID, 'longitude' );
113                        $items_removed = true;
114    }
115  }
117  // Tell core if we have more comments to work on still
118  $done = count( $comments ) < $number;
120  return array(
121    'items_removed' => $items_removed,
122    'items_retained' => false, // always false in this example
123    'messages' => array(), // no messages in this example
124    'done' => $done,
125  );
129The next thing the plugin needs to do is to register the callback by
130filtering the eraser array using the `wp_privacy_personal_data_erasers`
133When registering you provide a friendly name for the eraser (to aid in
134debugging - this friendly name is not shown to anyone at this time)
135and the callback, e.g.
138function register_my_plugin_eraser( $erasers ) {
139  $erasers[] = array(
140    'eraser_friendly_name' => __( 'Comment Location Plugin' ),
141    'callback'             => 'my_plugin_eraser',
142    );
143  return $erasers;
147  'wp_privacy_personal_data_erasers',
148  'register_my_plugin_eraser',
149  10
153And that's all there is to it! Your plugin will now clean up its personal