Privacy: Introduce `wp_privacy_additional_user_data` filter to make it easier to include additional user meta in a personal data export.
Props pbiron, xkon, garrett-eclipse, azaozz. Fixes #47509. git-svn-id: https://develop.svn.wordpress.org/trunk@47270 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
parent
0911aecf36
commit
0ad4121c91
|
@ -3006,6 +3006,52 @@ function wp_user_personal_data_exporter( $email_address ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the list of reserved names.
|
||||||
|
$reserved_names = array_values( $user_props_to_export );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter to extend the Users profile data for the privacy exporter.
|
||||||
|
*
|
||||||
|
* @since 5.4.0
|
||||||
|
*
|
||||||
|
* @param array $additional_user_profile_data {
|
||||||
|
* An array of name-value pairs of additional user data items. Default empty array.
|
||||||
|
*
|
||||||
|
* @type string $name The user-facing name of an item name-value pair,e.g. 'IP Address'.
|
||||||
|
* @type string $value The user-facing value of an item data pair, e.g. '50.60.70.0'.
|
||||||
|
* }
|
||||||
|
* @param WP_User $user The user whose data is being exported.
|
||||||
|
* @param string[] $reserved_names An array of reserved names. Any item in `$additional_user_data`
|
||||||
|
* that uses one of these for its `name` will not be included in the export.
|
||||||
|
*/
|
||||||
|
$_extra_data = apply_filters( 'wp_privacy_additional_user_profile_data', array(), $user, $reserved_names );
|
||||||
|
|
||||||
|
if ( is_array( $_extra_data ) && ! empty( $_extra_data ) ) {
|
||||||
|
// Remove items that use reserved names.
|
||||||
|
$extra_data = array_filter(
|
||||||
|
$_extra_data,
|
||||||
|
function( $item ) use ( $reserved_names ) {
|
||||||
|
return ! in_array( $item['name'], $reserved_names );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( count( $extra_data ) !== count( $_extra_data ) ) {
|
||||||
|
_doing_it_wrong(
|
||||||
|
__FUNCTION__,
|
||||||
|
sprintf(
|
||||||
|
/* translators: %s: wp_privacy_additional_user_profile_data */
|
||||||
|
__( 'Filter %s returned items with reserved names.' ),
|
||||||
|
'<code>wp_privacy_additional_user_profile_data</code>'
|
||||||
|
),
|
||||||
|
'5.4.0'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! empty( $extra_data ) ) {
|
||||||
|
$user_data_to_export = array_merge( $user_data_to_export, $extra_data );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$data_to_export[] = array(
|
$data_to_export[] = array(
|
||||||
'group_id' => 'user',
|
'group_id' => 'user',
|
||||||
'group_label' => __( 'User' ),
|
'group_label' => __( 'User' ),
|
||||||
|
|
|
@ -1794,4 +1794,133 @@ class Tests_User extends WP_UnitTestCase {
|
||||||
$this->assertEquals( 'Last Login', $actual['data'][1]['data'][3]['name'] );
|
$this->assertEquals( 'Last Login', $actual['data'][1]['data'][3]['name'] );
|
||||||
$this->assertEquals( 'January 29, 2020 09:13 AM', $actual['data'][1]['data'][3]['value'] );
|
$this->assertEquals( 'January 29, 2020 09:13 AM', $actual['data'][1]['data'][3]['value'] );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Testing the `wp_privacy_additional_user_profile_data` filter works.
|
||||||
|
*
|
||||||
|
* @ticket 47509
|
||||||
|
*/
|
||||||
|
function test_filter_wp_privacy_additional_user_profile_data() {
|
||||||
|
$test_user = new WP_User( self::$contrib_id );
|
||||||
|
|
||||||
|
add_filter( 'wp_privacy_additional_user_profile_data', array( $this, 'export_additional_user_profile_data' ) );
|
||||||
|
|
||||||
|
$actual = wp_user_personal_data_exporter( $test_user->user_email );
|
||||||
|
|
||||||
|
remove_filter( 'wp_privacy_additional_user_profile_data', array( $this, 'export_additional_user_profile_data' ) );
|
||||||
|
|
||||||
|
$this->assertTrue( $actual['done'] );
|
||||||
|
|
||||||
|
// Number of exported users.
|
||||||
|
$this->assertSame( 1, count( $actual['data'] ) );
|
||||||
|
|
||||||
|
// Number of exported user properties (the 11 core properties,
|
||||||
|
// plus 1 additional from the filter).
|
||||||
|
$this->assertSame( 12, count( $actual['data'][0]['data'] ) );
|
||||||
|
|
||||||
|
// Check that the item added by the filter was retained.
|
||||||
|
$this->assertSame(
|
||||||
|
1,
|
||||||
|
count(
|
||||||
|
wp_list_filter(
|
||||||
|
$actual['data'][0]['data'],
|
||||||
|
array(
|
||||||
|
'name' => 'Test Additional Data Name',
|
||||||
|
'value' => 'Test Additional Data Value',
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// _doing_wrong() should be called because the filter callback
|
||||||
|
// adds a item with a 'name' that is the same as one generated by core.
|
||||||
|
$this->setExpectedIncorrectUsage( 'wp_user_personal_data_exporter' );
|
||||||
|
add_filter( 'wp_privacy_additional_user_profile_data', array( $this, 'export_additional_user_profile_data_with_dup_name' ) );
|
||||||
|
|
||||||
|
$actual = wp_user_personal_data_exporter( $test_user->user_email );
|
||||||
|
|
||||||
|
remove_filter( 'wp_privacy_additional_user_profile_data', array( $this, 'export_additional_user_profile_data' ) );
|
||||||
|
|
||||||
|
$this->assertTrue( $actual['done'] );
|
||||||
|
|
||||||
|
// Number of exported users.
|
||||||
|
$this->assertSame( 1, count( $actual['data'] ) );
|
||||||
|
|
||||||
|
// Number of exported user properties
|
||||||
|
// (the 11 core properties, plus 1 additional from the filter).
|
||||||
|
$this->assertSame( 12, count( $actual['data'][0]['data'] ) );
|
||||||
|
|
||||||
|
// Check that the duplicate 'name' => 'User ID' was stripped.
|
||||||
|
$this->assertSame(
|
||||||
|
1,
|
||||||
|
count(
|
||||||
|
wp_list_filter(
|
||||||
|
$actual['data'][0]['data'],
|
||||||
|
array(
|
||||||
|
'name' => 'User ID',
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check that the item added by the filter was retained.
|
||||||
|
$this->assertSame(
|
||||||
|
1,
|
||||||
|
count(
|
||||||
|
wp_list_filter(
|
||||||
|
$actual['data'][0]['data'],
|
||||||
|
array(
|
||||||
|
'name' => 'Test Additional Data Name',
|
||||||
|
'value' => 'Test Additional Data Value',
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter callback to add additional profile data to the User Group on Export Requests.
|
||||||
|
*
|
||||||
|
* @ticket 47509
|
||||||
|
*
|
||||||
|
* @return array $additional_profile_data The additional user data.
|
||||||
|
*/
|
||||||
|
public function export_additional_user_profile_data() {
|
||||||
|
$additional_profile_data = array(
|
||||||
|
// This item should be retained and included in the export.
|
||||||
|
array(
|
||||||
|
'name' => 'Test Additional Data Name',
|
||||||
|
'value' => 'Test Additional Data Value',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return $additional_profile_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter callback to add additional profile data to the User Group on Export Requests.
|
||||||
|
*
|
||||||
|
* This callback should generate a `_doing_it_wrong()`.
|
||||||
|
*
|
||||||
|
* @ticket 47509
|
||||||
|
*
|
||||||
|
* @return array $additional_profile_data The additional user data.
|
||||||
|
*/
|
||||||
|
public function export_additional_user_profile_data_with_dup_name() {
|
||||||
|
$additional_profile_data = array(
|
||||||
|
// This item should be stripped out by wp_user_personal_data_exporter()
|
||||||
|
// because it's 'name' duplicates one exported by core.
|
||||||
|
array(
|
||||||
|
'name' => 'User ID',
|
||||||
|
'value' => 'Some User ID',
|
||||||
|
),
|
||||||
|
// This item should be retained and included in the export.
|
||||||
|
array(
|
||||||
|
'name' => 'Test Additional Data Name',
|
||||||
|
'value' => 'Test Additional Data Value',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return $additional_profile_data;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue