Index: src/wp-includes/functions.php
===================================================================
--- src/wp-includes/functions.php	(revision 42963)
+++ src/wp-includes/functions.php	(working copy)
@@ -6127,3 +6127,103 @@
 		), $email_change_email['message'], $email_change_email['headers']
 	);
 }
+
+/**
+ * Return an anonymized IPV4 or IPV6 address.
+ *
+ * @since 5.0.0
+ *
+ * @param  string $ip_addr The IPv4 or IPv6 address to be anonymized.
+ * @return string          The anonymized IP address.
+ */
+function wp_privacy_anonymize_ip( $ip_addr ) {
+	$ip_prefix = '';
+	$is_ipv4   = ( 3 === substr_count( $ip_addr, '.' ) );
+	$is_ipv6   = substr_count( $ip_addr, ':' ) > 1;
+
+	if ( $is_ipv6 && $is_ipv4 ) {
+		// IPv6 compatibility mode, temporarily strip the IPv6 part, and treat it like IPv4.
+		$ip_prefix = '::ffff:';
+		$ip_addr   = preg_replace( '/^\[?[0-9a-f:]*:/i', '', $ip_addr );
+		$ip_addr   = str_replace( ']', '', $ip_addr );
+		$is_ipv6   = false;
+	}
+
+	if ( $is_ipv6 ) {
+		// IPv6 addresses will always be enclosed in [] if there's a port.
+		$ip_start = 1;
+		$ip_end   = (int) strpos( $ip_addr, ']' ) - 1;
+		$netmask  = 'ffff:ffff:ffff:ffff:0000:0000:0000:0000';
+
+		// Strip the port (and [] from IPv6 addresses), if they exist.
+		if ( $ip_end > 0 ) {
+			$ip_addr = substr( $ip_addr, $ip_start, $ip_end );
+		}
+
+		// Partially anonymize the IP by reducing it to the corresponding network ID.
+		// This basically zeros the last eight octets of an IPV6 address.
+		// Note inet_pton and inet_ntop were not available on Windows platforms until PHP 5.3.0.
+		if ( function_exists( 'inet_pton' ) && function_exists( 'inet_ntop' ) ) {
+			$ip_addr = inet_ntop( inet_pton( $ip_addr ) & inet_pton( $netmask ) );
+		} else {
+			return '0.0.0.0';
+		}
+	} elseif ( $is_ipv4 ) {
+		// Strip any port and partially anonymize the IP.
+		$last_octet_position = strrpos( $ip_addr, '.' );
+		$ip_addr             = substr( $ip_addr, 0, $last_octet_position ) . '.0';
+	} else {
+		return '0.0.0.0';
+	}
+
+	// Restore the IPv6 prefix to compatibility mode addresses.
+	return $ip_prefix . $ip_addr;
+}
+
+/**
+ * Return uniform "anonymous" data by type.
+ *
+ * @since 5.0.0
+ *
+ * @param  string $data Optional The data to be anonymized.
+ * @param  string $type Optional The type of data to be anonymized.
+ * @return string                The anonymous data for the requested type.
+ */
+function wp_privacy_anonymize_data( $data = '', $type = '' ) {
+
+	switch ( $type ) {
+		case 'email':
+			$anonymous = 'deleted@site.invalid';
+			break;
+		case 'url':
+			$anonymous = 'https://site.invalid';
+			break;
+		case 'ip':
+			$anonymous = wp_privacy_anonymize_ip( $data );
+			break;
+		case 'date':
+			$anonymous = '0000-00-00 00:00:00';
+			break;
+		case 'text':
+			/* translators: deleted text */
+			$anonymous = __( '[deleted]' );
+			break;
+		case 'longtext':
+			/* translators: deleted long text */
+			$anonymous = __( 'This content was deleted by the author.' );
+			break;
+		default:
+			$anonymous = '';
+	}
+
+	/**
+	 * Filters the anonymous data for each type.
+	 *
+	 * @since 5.0.0
+	 *
+	 * @param string $anonymous Anonymized data.
+	 * @param string $data      Original data.
+	 * @param string $type      Type of the data.
+	 */
+	return apply_filters( 'wp_privacy_anonymize_data', $anonymous, $data, $type );
+}
Index: tests/phpunit/tests/functions/anonymization.php
===================================================================
--- tests/phpunit/tests/functions/anonymization.php	(nonexistent)
+++ tests/phpunit/tests/functions/anonymization.php	(working copy)
@@ -0,0 +1,64 @@
+<?php
+
+/**
+ * @group functions.php
+ * @group privacy
+ */
+class Tests_Functions_Anonymization extends WP_UnitTestCase {
+  function test_anonymize_invalid_ip() {
+    $ip_addrs = array( '', 'invalid', '0.0.0.0.0' );
+
+    foreach ( (array) $ip_addrs as $ip_addr ) {
+      $this->assertEquals( '0.0.0.0', wp_privacy_anonymize_data( $ip_addr, 'ip' ) );
+    }
+  }
+
+  function test_anonymize_ipv4() {
+    $ip_addrs = array(
+      '198.143.164.252' => '198.143.164.0',
+      '127.0.0.1'       => '127.0.0.0',
+    );
+
+    foreach ( (array) $ip_addrs as $ip_addr => $anonymized_ip_addr ) {
+      $this->assertEquals( $anonymized_ip_addr, wp_privacy_anonymize_data( $ip_addr, 'ip' ) );
+    }
+  }
+
+  function test_anonymize_ipv6() {
+    $ip_addrs = array(
+      '2001:0db8:0a0b:12f0:0000:0000:0000:0001' => '2001:db8:a0b:12f0::',
+      '2001:db8:a0b:12f0::1'                    => '2001:db8:a0b:12f0::',
+      '2001:db8::1'                             => '2001:db8::',
+      '::ffff:10.0.0.3'                         => '::ffff:10.0.0.0',
+      '[2001:db8:a0b:12f0::1]'                  => '2001:db8:a0b:12f0::',
+      '[2001:db8:a0b:12f0::1]:21'               => '2001:db8:a0b:12f0::',
+      '::1'                                     => '::',
+    );
+
+    foreach ( (array) $ip_addrs as $ip_addr => $anonymized_ip_addr ) {
+      $this->assertEquals( $anonymized_ip_addr, wp_privacy_anonymize_data( $ip_addr, 'ip' ) );
+    }
+  }
+
+  function test_anonymize_email() {
+    $this->assertEquals( 'deleted@site.invalid', wp_privacy_anonymize_data( 'bar@example.com', 'email' ) );
+  }
+
+  function test_anonymize_url() {
+    $this->assertEquals( 'https://site.invalid', wp_privacy_anonymize_data( 'https://example.com/author/username', 'url' ) );
+  }
+
+  function test_anonymize_date() {
+    $this->assertEquals( '0000-00-00 00:00:00', wp_privacy_anonymize_data( '2003-12-25 12:34:56', 'date' ) );
+  }
+
+  function test_anonymize_text() {
+    $text = __( 'Four score and seven years ago' );
+    $this->assertNotEquals( $text, wp_privacy_anonymize_data( $text, 'text' ) );
+  }
+
+  function test_anonymize_long_text() {
+    $text = __( 'Four score and seven years ago' );
+    $this->assertNotEquals( $text, wp_privacy_anonymize_data( $text, 'longtext' ) );
+  }
+}
