-
Notifications
You must be signed in to change notification settings - Fork 805
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[not verified] Jetpack Sync: Checksums: Add support for User and User…
… Meta tables. (#21139) * Initial commit * Change method visibility to allow easier extension on WPCOM. * Add changelog entry * Bump version * Major rewrite to rely on `WP_User` objects. Changed the method visibilities to allow easier extending. * Add `users` and `usermeta` to `checksum_all` * Small refactoring to allow better WPCOM integration. * reorder usermeta checksum to match the umeta_id used on WP.com. update the meta values to use the expand_user logic from the User modules (used during sync) and also apply sanitzation used on WP.com. This will allow for us to checksum directly against the db value. * Count the items distinctively. This is temporary and should be fixed in a more general sense. * Update the checksum generation to align with WP.com logic summation of individual key-values * not applicable comment * Distinct Usermeta count query empty check for meta. * Update the usermeta mapping to reference the users table directly instead of usermeta Co-authored-by: Matthew Denton <[email protected]>
- Loading branch information
Showing
4 changed files
with
233 additions
and
16 deletions.
There are no files selected for viewing
4 changes: 4 additions & 0 deletions
4
projects/packages/sync/changelog/add-jetpack-sync-checksums-support-for-users
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
Significance: patch | ||
Type: added | ||
|
||
Add support for checksumming user-related tabled - wp_users and wp_usermeta |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
169 changes: 169 additions & 0 deletions
169
projects/packages/sync/src/replicastore/class-table-checksum-usermeta.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
<?php | ||
/** | ||
* Table Checksums Class. | ||
* | ||
* @package automattic/jetpack-sync | ||
*/ | ||
|
||
namespace Automattic\Jetpack\Sync\Replicastore; | ||
|
||
use Automattic\Jetpack\Sync; | ||
use Automattic\Jetpack\Sync\Modules; | ||
use WP_Error; | ||
use WP_User_Query; | ||
|
||
/** | ||
* Class to handle Table Checksums for the User Meta table. | ||
*/ | ||
class Table_Checksum_Usermeta extends Table_Checksum { | ||
/** | ||
* Calculate the checksum based on provided range and filters. | ||
* | ||
* @param int|null $range_from The start of the range. | ||
* @param int|null $range_to The end of the range. | ||
* @param array|null $filter_values Additional filter values. Not used at the moment. | ||
* @param bool $granular_result If the returned result should be granular or only the checksum. | ||
* @param bool $simple_return_value If we want to use a simple return value for non-granular results (return only the checksum, without wrappers). | ||
* | ||
* @return array|mixed|object|WP_Error|null | ||
*/ | ||
public function calculate_checksum( $range_from = null, $range_to = null, $filter_values = null, $granular_result = false, $simple_return_value = true ) { | ||
|
||
if ( ! Sync\Settings::is_checksum_enabled() ) { | ||
return new WP_Error( 'checksum_disabled', 'Checksums are currently disabled.' ); | ||
} | ||
|
||
/** | ||
* First we need to fetch the user IDs for the users that we want to include in the range. | ||
* | ||
* To keep things a bit simple and avoid filtering issues, let's reuse the `build_filter_statement` that already | ||
* exists. Unfortunately we don't | ||
*/ | ||
global $wpdb; | ||
|
||
// This call depends on the `range_field` pointing to the `ID` field of the `users` table. Currently, "ID". | ||
$range_filter_statement = $this->build_filter_statement( $range_from, $range_to ); | ||
|
||
$query = " | ||
SELECT | ||
DISTINCT {$this->range_field} | ||
FROM | ||
{$this->table} | ||
WHERE | ||
{$range_filter_statement} | ||
"; | ||
|
||
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared | ||
$user_ids = $wpdb->get_col( $query ); | ||
|
||
// Chunk the array down to make sure we don't overload the database with queries that are too large. | ||
$chunked_user_ids = array_chunk( $user_ids, 500 ); | ||
|
||
$checksum_entries = array(); | ||
|
||
foreach ( $chunked_user_ids as $user_ids_chunk ) { | ||
$user_objects = $this->get_user_objects_by_ids( $user_ids_chunk ); | ||
|
||
foreach ( $user_objects as $user_object ) { | ||
// expand and sanitize desired meta based on WP.com logic. | ||
$user_object = $this->expand_and_sanitize_user_meta( $user_object ); | ||
|
||
// Generate checksum entry based on the serialized value if not empty. | ||
$checksum_entry = 0; | ||
if ( ! empty( $user_object->roles ) ) { | ||
$checksum_entry = crc32( implode( '#', array( $this->salt, 'roles', maybe_serialize( $user_object->roles ) ) ) ); | ||
} | ||
if ( ! empty( $user_object->allcaps ) ) { | ||
$checksum_entry += crc32( implode( '#', array( $this->salt, 'capabilities', maybe_serialize( $user_object->allcaps ) ) ) ); | ||
} | ||
if ( ! empty( $user_object->locale ) ) { | ||
$checksum_entry += crc32( implode( '#', array( $this->salt, 'locale', maybe_serialize( $user_object->locale ) ) ) ); | ||
} | ||
if ( ! empty( $user_object->allowed_mime_types ) ) { | ||
$checksum_entry += crc32( implode( '#', array( $this->salt, 'allowed_mime_types', maybe_serialize( $user_object->allowed_mime_types ) ) ) ); | ||
} | ||
$checksum_entries[ $user_object->ID ] = $checksum_entry; | ||
} | ||
} | ||
|
||
// Non-granular results need only to sum the different entries. | ||
if ( ! $granular_result ) { | ||
$checksum_sum = 0; | ||
foreach ( $checksum_entries as $entry ) { | ||
$checksum_sum += $entry; | ||
} | ||
|
||
if ( $simple_return_value ) { | ||
return $checksum_sum; | ||
} | ||
|
||
return array( | ||
'range' => $range_from . '-' . $range_to, | ||
'checksum' => $checksum_sum, | ||
); | ||
|
||
} | ||
|
||
// Granular results. | ||
$response = $checksum_entries; | ||
|
||
// Sort the return value for easier comparisons and code flows further down the line. | ||
ksort( $response ); | ||
|
||
return $response; | ||
} | ||
|
||
/** | ||
* Expand the User Object with additional meta santized by WP.com logic. | ||
* | ||
* @param mixed $user_object User Object from WP_User_Query. | ||
* | ||
* @return mixed $user_object expanded User Object. | ||
*/ | ||
protected function expand_and_sanitize_user_meta( $user_object ) { | ||
$user_module = Modules::get_module( 'users' ); | ||
// Expand User Objects based on Sync logic. | ||
$user_object = $user_module->expand_user( $user_object ); | ||
|
||
// Sanitize location. | ||
if ( ! empty( $user_object->locale ) ) { | ||
$user_object->locale = wp_strip_all_tags( $user_object->locale, true ); | ||
} | ||
|
||
// Sanitize allcaps. | ||
if ( ! empty( $user_object->allcaps ) ) { | ||
$user_object->allcaps = array_map( | ||
function ( $cap ) { | ||
return (bool) $cap; | ||
}, | ||
$user_object->allcaps | ||
); | ||
} | ||
|
||
// Sanitize allowed_mime_types. | ||
foreach ( $user_object->allowed_mime_types as $allowed_mime_type_short => $allowed_mime_type_long ) { | ||
$allowed_mime_type_short = wp_strip_all_tags( (string) $allowed_mime_type_short, true ); | ||
$allowed_mime_type_long = wp_strip_all_tags( (string) $allowed_mime_type_long, true ); | ||
$user_object->allowed_mime_types[ $allowed_mime_type_short ] = $allowed_mime_type_long; | ||
} | ||
|
||
// Sanitize roles. | ||
if ( is_array( $user_object->roles ) ) { | ||
$user_object->roles = array_map( 'sanitize_text_field', $user_object->roles ); | ||
} | ||
return $user_object; | ||
} | ||
|
||
/** | ||
* Gets a list of `WP_User` objects by their IDs | ||
* | ||
* @param array $ids List of IDs to fetch. | ||
* | ||
* @return array | ||
*/ | ||
protected function get_user_objects_by_ids( $ids ) { | ||
$user_query = new WP_User_Query( array( 'include' => $ids ) ); | ||
|
||
return $user_query->get_results(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters