updated plugin Jetpack Protect version 2.2.0

This commit is contained in:
2024-06-27 12:10:57 +00:00
committed by Gitium
parent ec9d8a5834
commit 938cef2946
218 changed files with 7469 additions and 1864 deletions

View File

@ -5,6 +5,94 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [2.16.6] - 2024-05-23
### Added
- Add reply to name setting for newsletters. [#37362]
## [2.16.5] - 2024-05-22
### Changed
- Internal updates.
## [2.16.4] - 2024-05-20
### Changed
- Replaced heredoc syntax with strings. [#37396]
## [2.16.3] - 2024-05-16
### Fixed
- Jetpack Sync: Fixed undefined array key Warnings in HPOS orders module [#37401]
## [2.16.2] - 2024-05-14
### Fixed
- Fix phpdoc type on `Replicastore_Interface::get_term()` `$taxonomy` arg. [#37344]
- Jetpack Sync: Ensure 'jetpack_sync_callable_whitelist' filter is respected when added late [#37370]
## [2.16.1] - 2024-05-09
### Changed
- Internal updates.
## [2.16.0] - 2024-05-08
### Added
- Options: sync WordAds inline ads toggle option [#37170]
## [2.15.1] - 2024-05-06
### Fixed
- Reimplement `Replicastore::get_user()` to not try to call a nonexistent method. [#37201]
- Sync:Disable jetpack_sync_queue custom table in case feature is enabled, but table does not exist in the DB. [#37108]
## [2.15.0] - 2024-04-30
### Added
- Add Woocommerce event remove_order_items to Jetpack Sync [#33748]
### Fixed
- Jetpack Sync: Prevent enqueueing invalid Woo HPOS order data [#37111]
## [2.14.0] - 2024-04-29
### Added
- Newsletters: Add reply to behaviour setting [#37011]
### Changed
- Sync: When publishing post, sending the actual post in the jetpack_published_post action to avoid sending unnecessary extra action. [#37071]
## [2.13.1] - 2024-04-25
### Changed
- Update dependencies.
## [2.13.0] - 2024-04-22
### Changed
- Added scheduled updates sync option. [#36877]
## [2.12.0] - 2024-04-15
### Added
- Add Scheduled Update Plugins option to synched options. [#36849]
## [2.11.1] - 2024-04-11
### Changed
- Internal updates.
## [2.11.0] - 2024-04-08
### Added
- Added social_notes_config option to sync. [#36671]
### Changed
- Sync: Sending queue size for pull jobs. [#36693]
## [2.10.5] - 2024-03-29
### Changed
- Update dependencies.
## [2.10.4] - 2024-03-27
### Fixed
- Fix handling of error message when sync wpcom rest api could not be enabled [#36578]
- Jetpack Sync: Prevent Fatal on send upon failing to enable WPCOM REST API feature [#36600]
## [2.10.3] - 2024-03-25
### Changed
- Internal updates.
## [2.10.2] - 2024-03-18
### Changed
- Internal updates.
## [2.10.1] - 2024-03-14
### Changed
- Internal updates.
@ -1072,6 +1160,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Packages: Move sync to a classmapped package
[2.16.6]: https://github.com/Automattic/jetpack-sync/compare/v2.16.5...v2.16.6
[2.16.5]: https://github.com/Automattic/jetpack-sync/compare/v2.16.4...v2.16.5
[2.16.4]: https://github.com/Automattic/jetpack-sync/compare/v2.16.3...v2.16.4
[2.16.3]: https://github.com/Automattic/jetpack-sync/compare/v2.16.2...v2.16.3
[2.16.2]: https://github.com/Automattic/jetpack-sync/compare/v2.16.1...v2.16.2
[2.16.1]: https://github.com/Automattic/jetpack-sync/compare/v2.16.0...v2.16.1
[2.16.0]: https://github.com/Automattic/jetpack-sync/compare/v2.15.1...v2.16.0
[2.15.1]: https://github.com/Automattic/jetpack-sync/compare/v2.15.0...v2.15.1
[2.15.0]: https://github.com/Automattic/jetpack-sync/compare/v2.14.0...v2.15.0
[2.14.0]: https://github.com/Automattic/jetpack-sync/compare/v2.13.1...v2.14.0
[2.13.1]: https://github.com/Automattic/jetpack-sync/compare/v2.13.0...v2.13.1
[2.13.0]: https://github.com/Automattic/jetpack-sync/compare/v2.12.0...v2.13.0
[2.12.0]: https://github.com/Automattic/jetpack-sync/compare/v2.11.1...v2.12.0
[2.11.1]: https://github.com/Automattic/jetpack-sync/compare/v2.11.0...v2.11.1
[2.11.0]: https://github.com/Automattic/jetpack-sync/compare/v2.10.5...v2.11.0
[2.10.5]: https://github.com/Automattic/jetpack-sync/compare/v2.10.4...v2.10.5
[2.10.4]: https://github.com/Automattic/jetpack-sync/compare/v2.10.3...v2.10.4
[2.10.3]: https://github.com/Automattic/jetpack-sync/compare/v2.10.2...v2.10.3
[2.10.2]: https://github.com/Automattic/jetpack-sync/compare/v2.10.1...v2.10.2
[2.10.1]: https://github.com/Automattic/jetpack-sync/compare/v2.10.0...v2.10.1
[2.10.0]: https://github.com/Automattic/jetpack-sync/compare/v2.9.0...v2.10.0
[2.9.0]: https://github.com/Automattic/jetpack-sync/compare/v2.8.1...v2.9.0

View File

@ -5,17 +5,19 @@
"license": "GPL-2.0-or-later",
"require": {
"php": ">=7.0",
"automattic/jetpack-connection": "^2.4.1",
"automattic/jetpack-constants": "^2.0.1",
"automattic/jetpack-identity-crisis": "^0.17.3",
"automattic/jetpack-connection": "^2.8.4",
"automattic/jetpack-constants": "^2.0.2",
"automattic/jetpack-identity-crisis": "^0.20.0",
"automattic/jetpack-password-checker": "^0.3.1",
"automattic/jetpack-ip": "^0.2.2",
"automattic/jetpack-roles": "^2.0.1",
"automattic/jetpack-status": "^2.1.2"
"automattic/jetpack-roles": "^2.0.2",
"automattic/jetpack-status": "^3.2.0"
},
"require-dev": {
"automattic/jetpack-changelogger": "^4.1.1",
"automattic/jetpack-changelogger": "^4.2.4",
"yoast/phpunit-polyfills": "1.1.0",
"automattic/jetpack-search": "@dev",
"automattic/jetpack-waf": "^0.16.8",
"automattic/wordbless": "@dev"
},
"suggest": {
@ -49,7 +51,13 @@
"link-template": "https://github.com/Automattic/jetpack-sync/compare/v${old}...v${new}"
},
"branch-alias": {
"dev-trunk": "2.10.x-dev"
"dev-trunk": "2.16.x-dev"
},
"dependencies": {
"test-only": [
"packages/search",
"packages/waf"
]
}
},
"config": {

View File

@ -57,7 +57,7 @@ class Actions {
* @access public
* @static
*
* @var Automattic\Jetpack\Sync\Sender
* @var \Automattic\Jetpack\Sync\Sender
*/
public static $sender = null;
@ -67,7 +67,7 @@ class Actions {
* @access public
* @static
*
* @var Automattic\Jetpack\Sync\Listener
* @var \Automattic\Jetpack\Sync\Listener
*/
public static $listener = null;
@ -542,13 +542,14 @@ class Actions {
$error_log = array_slice( $error_log, -4, null, true );
}
// Add new error indexed to time.
if ( Settings::is_wpcom_rest_api_enabled() ) {
$error_log[ (string) microtime( true ) ] = $error;
} else {
if ( isset( $rpc ) && ! empty( $rpc->get_last_response() ) ) {
$error_with_last_response = clone $error;
$error_with_last_response->add_data( $rpc->get_last_response() );
$error_log[ (string) microtime( true ) ] = $error_with_last_response;
} else {
$error_log[ (string) microtime( true ) ] = $error;
}
// Update the error log.
update_option( self::ERROR_LOG_PREFIX . $queue_id, $error_log );
return $error;
@ -562,7 +563,7 @@ class Actions {
);
}
if ( Settings::is_wpcom_rest_api_enabled() ) { // Return only processed items.
if ( isset( $response['processed_items'] ) ) { // Return only processed items.
$response = $response['processed_items'];
}
@ -588,6 +589,7 @@ class Actions {
// Don't start new sync if a full sync is in process.
$full_sync_module = Modules::get_module( 'full-sync' );
'@phan-var Modules\Full_Sync_Immediately|Modules\Full_Sync $full_sync_module';
if ( $full_sync_module && $full_sync_module->is_started() && ! $full_sync_module->is_finished() ) {
return false;
}
@ -610,6 +612,7 @@ class Actions {
*/
public static function do_only_first_initial_sync() {
$full_sync_module = Modules::get_module( 'full-sync' );
'@phan-var Modules\Full_Sync_Immediately|Modules\Full_Sync $full_sync_module';
if ( $full_sync_module && $full_sync_module->is_started() ) {
return false;
}
@ -632,6 +635,7 @@ class Actions {
}
$full_sync_module = Modules::get_module( 'full-sync' );
'@phan-var Modules\Full_Sync_Immediately|Modules\Full_Sync $full_sync_module';
if ( ! $full_sync_module ) {
return false;
@ -1040,7 +1044,8 @@ class Actions {
self::initialize_sender();
$sync_module = Modules::get_module( 'full-sync' );
$queue = self::$sender->get_sync_queue();
'@phan-var Modules\Full_Sync_Immediately|Modules\Full_Sync $sync_module';
$queue = self::$sender->get_sync_queue();
// _get_cron_array can be false
$cron_timestamps = ( _get_cron_array() ) ? array_keys( _get_cron_array() ) : array();
@ -1090,7 +1095,7 @@ class Actions {
);
// Verify $sync_module is not false.
if ( ( $sync_module ) && ! str_contains( get_class( $sync_module ), 'Full_Sync_Immediately' ) ) {
if ( $sync_module && ! $sync_module instanceof Modules\Full_Sync_Immediately ) {
$result['full_queue_size'] = $full_queue->size();
$result['full_queue_lag'] = $full_queue->lag();
}

View File

@ -88,6 +88,7 @@ class Defaults {
'jetpack_protect_key',
'jetpack_publicize_options',
'jetpack_relatedposts',
'jetpack_social_notes_config',
'jetpack_social_settings',
'jetpack_social_autoconvert_images',
'jetpack_sso_match_by_email',
@ -176,6 +177,7 @@ class Defaults {
'wordads_display_page',
'wordads_display_post',
'wordads_second_belowpost',
'wordads_inline_enabled',
'woocommerce_custom_orders_table_enabled',
'wp_mobile_app_promos',
'wp_mobile_excerpt',
@ -195,10 +197,13 @@ class Defaults {
'wpcom_reader_views_enabled',
'wpcom_site_setup',
'wpcom_subscription_emails_use_excerpt',
'jetpack_subscriptions_reply_to',
'jetpack_subscriptions_from_name',
'jetpack_verbum_subscription_modal',
'jetpack_blocks_disabled',
'jetpack_package_versions',
'jetpack_newsletters_publishing_default_frequency',
'jetpack_scheduled_plugins_update',
);
/**

View File

@ -402,8 +402,8 @@ class Functions {
*
* @deprecated 1.23.1
*
* @param callable $callable Function to retrieve URL option.
* @param string $new_value URL Protocol to set URLs to.
* @param string $callable Function name that was used to retrieve URL option.
* @param string $new_value URL Protocol to set URLs to.
* @return string Normalized URL.
*/
public static function get_protocol_normalized_url( $callable, $new_value ) {
@ -596,8 +596,8 @@ class Functions {
*
* @since 1.21.0
*
* @param array|obj $any Source data to be cleaned up.
* @param array $seen_nodes Built array of nodes.
* @param mixed $any Source data to be cleaned up.
* @param array $seen_nodes Built array of nodes.
*
* @return array
*/

View File

@ -52,7 +52,7 @@ class JSON_Deflate_Array_Codec implements Codec_Interface {
*
* @see https://gist.github.com/muhqu/820694
*
* @param string $any Value to serialize and wrap.
* @param mixed $any Value to serialize and wrap.
*
* @return false|string
*/

View File

@ -90,9 +90,11 @@ class Modules {
*
* @param string $module_name A module name.
*
* @return bool|Automattic\Jetpack\Sync\Modules\Module
* @return bool|\Automattic\Jetpack\Sync\Modules\Module
*/
public static function get_module( $module_name ) {
// @todo Better type hinting for Phan if https://github.com/phan/phan/issues/3842 gets fixed. Then clean up the `@phan-var` on all the callers.
foreach ( self::get_modules() as $module ) {
if ( $module->name() === $module_name ) {
return $module;
@ -134,7 +136,7 @@ class Modules {
*
* @param string $module_class The classname of a Jetpack sync module.
*
* @return Automattic\Jetpack\Sync\Modules\Module
* @return \Automattic\Jetpack\Sync\Modules\Module
*/
public static function load_module( $module_class ) {
return new $module_class();
@ -146,13 +148,14 @@ class Modules {
* @access public
* @static
*
* @param Automattic\Jetpack\Sync\Modules\Module $module Instance of a Jetpack sync module.
* @param \Automattic\Jetpack\Sync\Modules\Module $module Instance of a Jetpack sync module.
*
* @return Automattic\Jetpack\Sync\Modules\Module
* @return \Automattic\Jetpack\Sync\Modules\Module
*/
public static function set_module_defaults( $module ) {
$module->set_defaults();
if ( method_exists( $module, 'set_late_default' ) ) {
// @phan-suppress-next-line PhanUndeclaredMethodInCallable -- https://github.com/phan/phan/issues/1204
add_action( 'init', array( $module, 'set_late_default' ), 90 );
}
return $module;

View File

@ -12,7 +12,7 @@ namespace Automattic\Jetpack\Sync;
*/
class Package_Version {
const PACKAGE_VERSION = '2.10.1';
const PACKAGE_VERSION = '2.16.6';
const PACKAGE_SLUG = 'sync';

View File

@ -199,7 +199,7 @@ class Queue {
*
* @param int $buffer_size Size of the buffer to checkout.
*
* @return Automattic\Jetpack\Sync\Queue_Buffer|bool|int|\WP_Error
* @return \Automattic\Jetpack\Sync\Queue_Buffer|bool|int|\WP_Error
*/
public function checkout( $buffer_size ) {
if ( $this->get_checkout_id() ) {
@ -348,7 +348,7 @@ class Queue {
/**
* Check in the queue.
*
* @param Automattic\Jetpack\Sync\Queue_Buffer $buffer Queue_Buffer object.
* @param \Automattic\Jetpack\Sync\Queue_Buffer $buffer Queue_Buffer object.
*
* @return bool|\WP_Error
*/
@ -367,8 +367,8 @@ class Queue {
/**
* Close the buffer.
*
* @param Automattic\Jetpack\Sync\Queue_Buffer $buffer Queue_Buffer object.
* @param null|array $ids_to_remove Ids to remove from the queue.
* @param \Automattic\Jetpack\Sync\Queue_Buffer $buffer Queue_Buffer object.
* @param null|array $ids_to_remove Ids to remove from the queue.
*
* @return bool|\WP_Error
*/
@ -653,7 +653,7 @@ class Queue {
/**
* Return true if the buffer is still valid or an Error other wise.
*
* @param Automattic\Jetpack\Sync\Queue_Buffer $buffer The Queue_Buffer.
* @param \Automattic\Jetpack\Sync\Queue_Buffer $buffer The Queue_Buffer.
*
* @return bool|WP_Error
*/

View File

@ -82,7 +82,8 @@ class Replicastore implements Replicastore_Interface {
*/
public function term_count() {
global $wpdb;
return $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->terms" );
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
return (int) $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->terms" );
}
/**
@ -94,7 +95,8 @@ class Replicastore implements Replicastore_Interface {
*/
public function term_taxonomy_count() {
global $wpdb;
return $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->term_taxonomy" );
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
return (int) $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->term_taxonomy" );
}
/**
@ -106,7 +108,8 @@ class Replicastore implements Replicastore_Interface {
*/
public function term_relationship_count() {
global $wpdb;
return $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->term_relationships" );
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
return (int) $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->term_relationships" );
}
/**
@ -140,8 +143,8 @@ class Replicastore implements Replicastore_Interface {
$where .= ' AND ID <= ' . (int) $max_id;
}
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
return $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->posts WHERE $where" );
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
return (int) $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->posts WHERE $where" );
}
/**
@ -319,8 +322,8 @@ class Replicastore implements Replicastore_Interface {
$where .= ' AND comment_ID <= ' . (int) $max_id;
}
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
return $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->comments WHERE $where" );
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
return (int) $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->comments WHERE $where" );
}
/**
@ -874,9 +877,9 @@ class Replicastore implements Replicastore_Interface {
*
* @access public
*
* @param string $taxonomy Taxonomy slug.
* @param int $term_id ID of the term.
* @param string $term_key ID Field `term_id` or `term_taxonomy_id`.
* @param string|false $taxonomy Taxonomy slug.
* @param int $term_id ID of the term.
* @param string $term_key ID Field `term_id` or `term_taxonomy_id`.
*
* @return \WP_Term|WP_Error Term object on success, \WP_Error object on failure.
*/
@ -1086,10 +1089,11 @@ class Replicastore implements Replicastore_Interface {
* @access public
*
* @param int $user_id User ID.
* @return \WP_User User object.
* @return \WP_User|null User object, or `null` if user invalid/not found.
*/
public function get_user( $user_id ) {
return \WP_User::get_instance( $user_id );
$user = get_user_by( 'id', $user_id );
return $user instanceof \WP_User ? $user : null;
}
/**
@ -1392,6 +1396,7 @@ class Replicastore implements Replicastore_Interface {
* Used in methods that are not implemented and shouldn't be invoked.
*
* @access private
* @return never
* @throws Exception If this method is invoked.
*/
private function invalid_call() {

View File

@ -698,6 +698,7 @@ class REST_Endpoints {
// Update Full Sync Status if queue is "full_sync".
if ( 'full_sync' === $queue_name ) {
$full_sync_module = Modules::get_module( 'full-sync' );
'@phan-var Modules\Full_Sync_Immediately|Modules\Full_Sync $full_sync_module';
$full_sync_module->update_sent_progress_action( $items );
}

View File

@ -74,6 +74,7 @@ class REST_Sender {
'skipped_items' => $skipped_items_ids,
'codec' => $encode ? $sender->get_codec()->name() : null,
'sent_timestamp' => time(),
'queue_size' => $queue->size(),
);
}

View File

@ -128,7 +128,7 @@ class Sender {
*
* @access private
*
* @var Automattic\Jetpack\Sync\Queue
* @var \Automattic\Jetpack\Sync\Queue
*/
private $sync_queue;
@ -137,7 +137,7 @@ class Sender {
*
* @access private
*
* @var Automattic\Jetpack\Sync\Queue
* @var \Automattic\Jetpack\Sync\Queue
*/
private $full_sync_queue;
@ -146,7 +146,7 @@ class Sender {
*
* @access private
*
* @var Automattic\Jetpack\Sync\Codec_Interface
* @var \Automattic\Jetpack\Sync\Codec_Interface
*/
private $codec;
@ -165,7 +165,7 @@ class Sender {
* @access private
* @static
*
* @var Automattic\Jetpack\Sync\Sender
* @var \Automattic\Jetpack\Sync\Sender
*/
private static $instance;
@ -292,6 +292,7 @@ class Sender {
*/
public function do_full_sync() {
$sync_module = Modules::get_module( 'full-sync' );
'@phan-var Modules\Full_Sync_Immediately|Modules\Full_Sync $sync_module';
if ( ! $sync_module ) {
return;
}
@ -313,7 +314,7 @@ class Sender {
$this->continue_full_sync_enqueue();
// immediate full sync sends data in continue_full_sync_enqueue.
if ( ! str_contains( get_class( $sync_module ), 'Full_Sync_Immediately' ) ) {
if ( ! $sync_module instanceof Modules\Full_Sync_Immediately ) {
return $this->do_sync_and_set_delays( $this->full_sync_queue );
} else {
$status = $sync_module->get_status();
@ -342,7 +343,9 @@ class Sender {
return false;
}
Modules::get_module( 'full-sync' )->continue_enqueuing();
$full_sync_module = Modules::get_module( 'full-sync' );
'@phan-var Modules\Full_Sync_Immediately|Modules\Full_Sync $full_sync_module';
$full_sync_module->continue_enqueuing();
$this->set_next_sync_time( time() + $this->get_enqueue_wait_time(), 'full-sync-enqueue' );
}
@ -391,7 +394,7 @@ class Sender {
*
* @see \Automattic\Jetpack\Sync\Dedicated_Sender::can_spawn_dedicated_sync_request
*/
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- This is just a constant string used for Validation.
echo Dedicated_Sender::DEDICATED_SYNC_VALIDATION_STRING;
// Try to disconnect the request as quickly as possible and process things in the background.
@ -439,7 +442,7 @@ class Sender {
*
* @access public
*
* @param Automattic\Jetpack\Sync\Queue $queue Queue object.
* @param \Automattic\Jetpack\Sync\Queue $queue Queue object.
*
* @return boolean|WP_Error True if this sync sending was successful, error object otherwise.
*/
@ -507,8 +510,8 @@ class Sender {
*
* @access public
*
* @param (array|Automattic\Jetpack\Sync\Queue_Buffer) $buffer_or_items Queue buffer or array of objects.
* @param boolean $encode Whether to encode the items.
* @param (array|\Automattic\Jetpack\Sync\Queue_Buffer) $buffer_or_items Queue buffer or array of objects.
* @param boolean $encode Whether to encode the items.
* @return array Sync items to send.
*/
public function get_items_to_send( $buffer_or_items, $encode = true ) {
@ -587,7 +590,7 @@ class Sender {
*
* @access public
*
* @param Automattic\Jetpack\Sync\Queue $queue Queue object.
* @param \Automattic\Jetpack\Sync\Queue $queue Queue object.
*
* @return boolean|WP_Error True if this sync sending was successful, error object otherwise.
*/
@ -702,7 +705,7 @@ class Sender {
* @param string $action_name The action.
* @param array $data The data associated with the action.
*
* @return Items processed. TODO: this doesn't make much sense anymore, it should probably be just a bool.
* @return array Items processed. TODO: this doesn't make much sense anymore, it should probably be just a bool.
*/
public function send_action( $action_name, $data = null ) {
if ( ! Settings::is_sender_enabled( 'full_sync' ) ) {
@ -790,7 +793,7 @@ class Sender {
*
* @access public
*
* @return Automattic\Jetpack\Sync\Queue Queue object.
* @return \Automattic\Jetpack\Sync\Queue Queue object.
*/
public function get_sync_queue() {
return $this->sync_queue;
@ -801,7 +804,7 @@ class Sender {
*
* @access public
*
* @return Automattic\Jetpack\Sync\Queue Queue object.
* @return \Automattic\Jetpack\Sync\Queue Queue object.
*/
public function get_full_sync_queue() {
return $this->full_sync_queue;
@ -812,7 +815,7 @@ class Sender {
*
* @access public
*
* @return Automattic\Jetpack\Sync\Codec_Interface Codec object.
* @return \Automattic\Jetpack\Sync\Codec_Interface Codec object.
*/
public function get_codec() {
return $this->codec;

View File

@ -19,7 +19,7 @@ class Server {
*
* @access private
*
* @var Automattic\Jetpack\Sync\Codec_Interface
* @var \Automattic\Jetpack\Sync\Codec_Interface
*/
private $codec;

View File

@ -270,10 +270,13 @@ class Settings {
$sender->send_action( 'jetpack_sync_storage_error_custom_migrate', $data );
}
} elseif ( $old_value && ! $value ) {
/**
* The custom table has been disabled, migrate what we can from the custom table to the options table.
*/
Queue_Storage_Table::migrate_from_custom_table_to_options_table();
if ( ! get_transient( Queue_Storage_Table::CUSTOM_QUEUE_TABLE_DISABLE_WPDB_ERROR_NOT_EXIST_FLAG ) ) {
/**
* The custom table has been disabled, migrate what we can from the custom table to the options table unless
* the custom table doesn't exist in the DB.
*/
Queue_Storage_Table::migrate_from_custom_table_to_options_table();
}
}
}
@ -316,7 +319,7 @@ class Settings {
$data = array(
'timestamp' => microtime( true ),
'response_code' => $items->get_error_code(),
'response_body' => $items->get_error_data() ? trim( $items->get_error_data() ) : '',
'response_body' => $items->get_error_message() ?? '',
);
$sender->send_action( 'jetpack_sync_wpcom_rest_api_enable_error', $data );
}

View File

@ -414,9 +414,9 @@ interface Replicastore_Interface {
*
* @access public
*
* @param string $taxonomy Taxonomy slug.
* @param int $term_id ID of the term.
* @param string $term_key ID Field `term_id` or `term_taxonomy_id`.
* @param string|false $taxonomy Taxonomy slug.
* @param int $term_id ID of the term.
* @param string $term_key ID Field `term_id` or `term_taxonomy_id`.
*/
public function get_term( $taxonomy, $term_id, $term_key = 'term_id' );
@ -486,6 +486,7 @@ interface Replicastore_Interface {
* @access public
*
* @param int $user_id User ID.
* @return \WP_User|null User object, or `null` if user invalid/not found.
*/
public function get_user( $user_id );

View File

@ -109,6 +109,28 @@ class Callables extends Module {
$this->force_send_callables_on_next_tick = false; // Resets here as well mostly for tests.
}
/**
* Set module defaults at a later time.
* Reset the callable whitelist if needed to account for plugins adding the 'jetpack_sync_callable_whitelist'
* and 'jetpack_sync_multisite_callable_whitelist' filters late.
*
* @see Automattic\Jetpack\Sync\Modules::set_module_defaults
* @access public
*/
public function set_late_default() {
if ( is_multisite() ) {
$late_callables = array_merge(
apply_filters( 'jetpack_sync_callable_whitelist', array() ),
apply_filters( 'jetpack_sync_multisite_callable_whitelist', array() )
);
} else {
$late_callables = apply_filters( 'jetpack_sync_callable_whitelist', array() );
}
if ( ! empty( $late_callables ) && is_array( $late_callables ) ) {
$this->callable_whitelist = array_merge( $this->callable_whitelist, $late_callables );
}
}
/**
* Initialize callables action listeners.
*
@ -404,7 +426,7 @@ class Callables extends Module {
$link_element = $link_elements->item( 0 );
// phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
if ( $link_element->hasAttribute( 'href' ) && $link_element->nodeValue ) {
if ( $link_element instanceof \DOMElement && $link_element->hasAttribute( 'href' ) && $link_element->nodeValue ) {
$link_url = trim( $link_element->getAttribute( 'href' ) );
// Add the full admin path to the url if the plugin did not provide it.

View File

@ -240,6 +240,7 @@ class Comments extends Module {
public function filter_blacklisted_post_types( $args ) {
$post_id = $args[0];
$posts_module = Modules::get_module( 'posts' );
'@phan-var Posts $posts_module';
if ( false !== $posts_module && ! $posts_module->is_post_type_allowed( $post_id ) ) {
return false;
@ -341,8 +342,8 @@ class Comments extends Module {
}
// TODO: Call $wpdb->prepare on the following query.
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
$count = $wpdb->get_var( $query );
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
$count = (int) $wpdb->get_var( $query );
return (int) ceil( $count / self::ARRAY_CHUNK_SIZE );
}

View File

@ -87,7 +87,9 @@ class Full_Sync_Immediately extends Module {
}
if ( isset( $full_sync_config['users'] ) && 'initial' === $full_sync_config['users'] ) {
$full_sync_config['users'] = Modules::get_module( 'users' )->get_initial_sync_user_config();
$users_module = Modules::get_module( 'users' );
'@phan-var Users $users_module';
$full_sync_config['users'] = $users_module->get_initial_sync_user_config();
}
$this->update_status(
@ -412,8 +414,8 @@ class Full_Sync_Immediately extends Module {
/**
* Select configured and not finished modules.
*
* @param Module $module
* @return bool
* @var $module Module
*/
function ( $module ) use ( $status ) {
// Skip module if not configured for this sync or module is done.

View File

@ -125,6 +125,7 @@ class Full_Sync extends Module {
}
if ( 'users' === $module_name && 'initial' === $module_config ) {
'@phan-var Users $module';
$module_config = $module->get_initial_sync_user_config();
}
@ -212,7 +213,7 @@ class Full_Sync extends Module {
/**
* Select configured and not finished modules.
*
* @var $module Module
* @param Module $module
* @return bool
*/
function ( $module ) use ( $configs, $enqueue_status ) {

View File

@ -293,19 +293,19 @@ abstract class Module {
* @return array|object|null
*/
public function get_next_chunk( $config, $status, $chunk_size ) {
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery
global $wpdb;
return $wpdb->get_col(
<<<SQL
SELECT {$this->id_field()}
FROM {$wpdb->{$this->table_name()}}
WHERE {$this->get_where_sql( $config )}
AND {$this->id_field()} < {$status['last_sent']}
ORDER BY {$this->id_field()}
DESC LIMIT {$chunk_size}
SQL
"
SELECT {$this->id_field()}
FROM {$wpdb->{$this->table_name()}}
WHERE {$this->get_where_sql( $config )}
AND {$this->id_field()} < {$status['last_sent']}
ORDER BY {$this->id_field()}
DESC LIMIT {$chunk_size}
"
);
// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery
}
/**
@ -319,13 +319,13 @@ SQL
global $wpdb;
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.DirectDatabaseQuery.DirectQuery
return $wpdb->get_var(
<<<SQL
SELECT {$this->id_field()}
FROM {$wpdb->{$this->table_name()}}
WHERE {$this->get_where_sql( $config )}
ORDER BY {$this->id_field()}
LIMIT 1
SQL
"
SELECT {$this->id_field()}
FROM {$wpdb->{$this->table_name()}}
WHERE {$this->get_where_sql( $config )}
ORDER BY {$this->id_field()}
LIMIT 1
"
);
// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.DirectDatabaseQuery.DirectQuery
}
@ -631,8 +631,8 @@ SQL
$table = $wpdb->{$this->table_name()};
$where = $this->get_where_sql( $config );
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
return $wpdb->get_var( "SELECT COUNT(*) FROM $table WHERE $where" );
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
return (int) $wpdb->get_var( "SELECT COUNT(*) FROM $table WHERE $where" );
}
/**

View File

@ -8,6 +8,7 @@
namespace Automattic\Jetpack\Sync\Modules;
use Automattic\Jetpack\Constants as Jetpack_Constants;
use WP_Error;
/**
* Class to handle sync for plugins.
@ -121,6 +122,7 @@ class Plugins extends Module {
// For plugin installer.
if ( empty( $plugins ) && method_exists( $upgrader, 'plugin_info' ) ) {
// @phan-suppress-next-line PhanUndeclaredMethod -- Checked above. See also https://github.com/phan/phan/issues/1204.
$plugins = array( $upgrader->plugin_info() );
}
@ -212,6 +214,7 @@ class Plugins extends Module {
* @return array|boolean Error on error, false otherwise.
*/
private function get_errors( $skin ) {
// @phan-suppress-next-line PhanUndeclaredMethod -- Checked before being called. See also https://github.com/phan/phan/issues/1204.
$errors = method_exists( $skin, 'get_errors' ) ? $skin->get_errors() : null;
if ( is_wp_error( $errors ) ) {
$error_code = $errors->get_error_code();
@ -284,34 +287,33 @@ class Plugins extends Module {
*/
public function plugin_edit_ajax() {
// This validation is based on wp_edit_theme_plugin_file().
$args = wp_unslash( $_POST );
if ( empty( $args['file'] ) ) {
if ( empty( $_POST['file'] ) ) {
return;
}
$file = $args['file'];
$file = wp_unslash( $_POST['file'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Validated manually just after.
if ( 0 !== validate_file( $file ) ) {
return;
}
if ( ! isset( $args['newcontent'] ) ) {
if ( ! isset( $_POST['newcontent'] ) ) {
return;
}
if ( ! isset( $args['nonce'] ) ) {
if ( ! isset( $_POST['nonce'] ) ) {
return;
}
if ( empty( $args['plugin'] ) ) {
if ( empty( $_POST['plugin'] ) ) {
return;
}
$plugin = $args['plugin'];
$plugin = wp_unslash( $_POST['plugin'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Validated manually just after.
if ( ! current_user_can( 'edit_plugins' ) ) {
return;
}
if ( ! wp_verify_nonce( $args['nonce'], 'edit-plugin_' . $file ) ) {
if ( ! wp_verify_nonce( $_POST['nonce'], 'edit-plugin_' . $file ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput -- WP core doesn't pre-sanitize nonces either.
return;
}
$plugins = get_plugins();

View File

@ -151,7 +151,7 @@ class Posts extends Module {
add_action( 'jetpack_sync_save_post', $callable, 10, 4 );
add_action( 'deleted_post', $callable, 10 );
add_action( 'jetpack_published_post', $callable, 10, 2 );
add_action( 'jetpack_published_post', $callable, 10, 3 );
add_filter( 'jetpack_sync_before_enqueue_deleted_post', array( $this, 'filter_blacklisted_post_types_deleted' ) );
add_action( 'transition_post_status', array( $this, 'save_published' ), 10, 3 );
@ -161,6 +161,7 @@ class Posts extends Module {
$this->init_meta_whitelist_handler( 'post', array( $this, 'filter_meta' ) );
add_filter( 'jetpack_sync_before_enqueue_jetpack_sync_save_post', array( $this, 'filter_jetpack_sync_before_enqueue_jetpack_sync_save_post' ) );
add_filter( 'jetpack_sync_before_enqueue_jetpack_published_post', array( $this, 'filter_jetpack_sync_before_enqueue_jetpack_published_post' ) );
add_action( 'jetpack_daily_akismet_meta_cleanup_before', array( $this, 'daily_akismet_meta_cleanup_before' ) );
add_action( 'jetpack_daily_akismet_meta_cleanup_after', array( $this, 'daily_akismet_meta_cleanup_after' ) );
@ -232,7 +233,7 @@ class Posts extends Module {
add_filter( 'jetpack_sync_before_send_deleted_post_meta', array( $this, 'trim_post_meta' ) );
// Full sync.
$sync_module = Modules::get_module( 'full-sync' );
if ( $sync_module && str_contains( get_class( $sync_module ), 'Full_Sync_Immediately' ) ) {
if ( $sync_module instanceof Full_Sync_Immediately ) {
add_filter( 'jetpack_sync_before_send_jetpack_full_sync_posts', array( $this, 'add_term_relationships' ) );
} else {
add_filter( 'jetpack_sync_before_send_jetpack_full_sync_posts', array( $this, 'expand_posts_with_metadata_and_terms' ) );
@ -269,8 +270,8 @@ class Posts extends Module {
global $wpdb;
$query = "SELECT count(*) FROM $wpdb->posts WHERE " . $this->get_where_sql( $config );
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
$count = $wpdb->get_var( $query );
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
$count = (int) $wpdb->get_var( $query );
return (int) ceil( $count / self::ARRAY_CHUNK_SIZE );
}
@ -351,6 +352,18 @@ class Posts extends Module {
return array( $post_id, $this->filter_post_content_and_add_links( $post ), $update, $previous_state );
}
/**
* Add filtered post content.
*
* @param array $args Hook arguments.
* @return array Hook arguments.
*/
public function filter_jetpack_sync_before_enqueue_jetpack_published_post( $args ) {
list( $post_id, $flags, $post ) = $args;
return array( $post_id, $flags, $this->filter_post_content_and_add_links( $post ) );
}
/**
* Filter all blacklisted post types.
*
@ -605,12 +618,10 @@ class Posts extends Module {
* The 2nd request is to update post meta, which is not supported on WP REST API.
* When syncing post data, we will include if this was a meta box update.
*
* @todo Implement nonce verification.
*
* @return boolean Whether this is a Gutenberg meta box update.
*/
public function is_gutenberg_meta_box_update() {
// phpcs:disable WordPress.Security.NonceVerification.Missing, WordPress.Security.NonceVerification.Recommended
private function is_gutenberg_meta_box_update() {
// phpcs:disable WordPress.Security.NonceVerification.Missing, WordPress.Security.NonceVerification.Recommended -- We only check the request to determine if this is a Gutenberg meta box update, and we only use the result to set a boolean logged in the sync event. If anyone anywhere else gets the flag and does something CSRF-able with it, they should ensure that a nonce has been checked.
return (
isset( $_POST['action'], $_GET['classic-editor'], $_GET['meta_box'] ) &&
'editpost' === $_POST['action'] &&
@ -732,10 +743,6 @@ class Posts extends Module {
// Only Send Pulished Post event if post_type is not blacklisted.
if ( ! in_array( $post->post_type, Settings::get_setting( 'post_types_blacklist' ), true ) ) {
// Refreshing the post in the cache site before triggering the publish event.
// The true parameter means that it's an update action, not create action.
$this->wp_insert_post( $post_ID, $post, true );
/**
* Action that gets synced when a post type gets published.
*
@ -744,8 +751,9 @@ class Posts extends Module {
*
* @param int $post_ID
* @param mixed array $flags post flags that are added to the post
* @param WP_Post $post The post object
*/
do_action( 'jetpack_published_post', $post_ID, $flags );
do_action( 'jetpack_published_post', $post_ID, $flags, $post );
}
unset( $this->just_published[ $post_ID ] );

View File

@ -119,10 +119,10 @@ class Term_Relationships extends Module {
*/
$objects = $wpdb->get_results( $wpdb->prepare( "SELECT object_id, term_taxonomy_id FROM $wpdb->term_relationships WHERE ( object_id = %d AND term_taxonomy_id < %d ) OR ( object_id < %d ) ORDER BY object_id DESC, term_taxonomy_id DESC LIMIT %d", $last_object_enqueued['object_id'], $last_object_enqueued['term_taxonomy_id'], $last_object_enqueued['object_id'], $limit ), ARRAY_A );
// Request term relationships in groups of N for efficiency.
$objects_count = is_countable( $objects ) ? count( $objects ) : 0;
if ( ! $objects_count ) {
if ( ! is_countable( $objects ) || count( $objects ) === 0 ) {
return array( $items_enqueued_count, true );
}
$objects_count = count( $objects );
$items = array_chunk( $objects, $term_relationships_full_sync_item_size );
$last_object_enqueued = $this->bulk_enqueue_full_sync_term_relationships( $items, $last_object_enqueued );
$items_enqueued_count += count( $items );
@ -227,8 +227,8 @@ class Term_Relationships extends Module {
$query = "SELECT COUNT(*) FROM $wpdb->term_relationships";
// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared
$count = $wpdb->get_var( $query );
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
$count = (int) $wpdb->get_var( $query );
return (int) ceil( $count / Settings::get_setting( 'term_relationships_full_sync_item_size' ) );
}

View File

@ -181,8 +181,8 @@ class Terms extends Module {
$query .= ' WHERE ' . $where_sql;
}
// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared
$count = $wpdb->get_var( $query );
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
$count = (int) $wpdb->get_var( $query );
return (int) ceil( $count / self::ARRAY_CHUNK_SIZE );
}

View File

@ -63,8 +63,6 @@ class Themes extends Module {
*
* @access public
*
* @todo Implement nonce verification
*
* @param array $instance The current widget instance's settings.
* @param array $new_instance Array of new widget settings.
* @param array $old_instance Array of old widget settings.
@ -77,7 +75,7 @@ class Themes extends Module {
}
// Don't trigger sync action if this is an ajax request, because Customizer makes them during preview before saving changes.
// phpcs:disable WordPress.Security.NonceVerification.Missing
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Not doing anything with or in response to the $_POST data. We're only using $_POST['customized'] to early return if this is an ajax request from Customizer.
if ( defined( 'DOING_AJAX' ) && DOING_AJAX && isset( $_POST['customized'] ) ) {
return $instance;
}
@ -192,7 +190,7 @@ class Themes extends Module {
$query_params = array();
wp_parse_str( $url['query'], $query_params );
if (
! isset( $_POST['newcontent'] ) ||
! isset( $_POST['newcontent'] ) || // phpcs:ignore WordPress.Security.NonceVerification.Missing -- 'wp_redirect' gets fired for a lot of things. We're only using $_POST['newcontent'] to limit action to redirects from theme edits, we're not doing anything with or in response to the post itself.
! isset( $query_params['file'] ) ||
! isset( $query_params['theme'] ) ||
! isset( $query_params['updated'] )
@ -226,29 +224,28 @@ class Themes extends Module {
* @todo Refactor to use WP_Filesystem instead of fopen()/fclose().
*/
public function theme_edit_ajax() {
$args = wp_unslash( $_POST );
if ( empty( $args['theme'] ) ) {
// This validation is based on wp_edit_theme_plugin_file().
if ( empty( $_POST['theme'] ) ) {
return;
}
if ( empty( $args['file'] ) ) {
if ( empty( $_POST['file'] ) ) {
return;
}
$file = $args['file'];
$file = wp_unslash( $_POST['file'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Validated manually just after.
if ( 0 !== validate_file( $file ) ) {
return;
}
if ( ! isset( $args['newcontent'] ) ) {
if ( ! isset( $_POST['newcontent'] ) ) {
return;
}
if ( ! isset( $args['nonce'] ) ) {
if ( ! isset( $_POST['nonce'] ) ) {
return;
}
$stylesheet = $args['theme'];
$stylesheet = wp_unslash( $_POST['theme'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Validated manually just after.
if ( 0 !== validate_file( $stylesheet ) ) {
return;
}
@ -262,7 +259,7 @@ class Themes extends Module {
return;
}
if ( ! wp_verify_nonce( $args['nonce'], 'edit-theme_' . $stylesheet . '_' . $file ) ) {
if ( ! wp_verify_nonce( $_POST['nonce'], 'edit-theme_' . $stylesheet . '_' . $file ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput -- WP core doesn't pre-sanitize nonces either.
return;
}
@ -383,6 +380,7 @@ class Themes extends Module {
}
if ( 'install' === $details['action'] ) {
// @phan-suppress-next-line PhanUndeclaredMethod -- Checked above. See also https://github.com/phan/phan/issues/1204.
$theme = $upgrader->theme_info();
if ( ! $theme instanceof \WP_Theme ) {
return;

View File

@ -180,7 +180,7 @@ class Users extends Module {
* @access private
*
* @param mixed $user User object or ID.
* @return \WP_User User object, or `null` if user invalid/not found.
* @return \WP_User|null User object, or `null` if user invalid/not found.
*/
private function get_user( $user ) {
if ( is_numeric( $user ) ) {
@ -726,8 +726,8 @@ class Users extends Module {
$query .= ' WHERE ' . $where_sql;
}
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
$count = $wpdb->get_var( $query );
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
$count = (int) $wpdb->get_var( $query );
return (int) ceil( $count / self::ARRAY_CHUNK_SIZE );
}

View File

@ -201,6 +201,9 @@ class WooCommerce_HPOS_Orders extends Module {
* @return array
*/
public function expand_order_object( $args ) {
if ( ! is_array( $args ) || ! isset( $args[0] ) ) {
return false;
}
$order_object = $args[0];
if ( is_int( $order_object ) ) {
@ -259,7 +262,7 @@ class WooCommerce_HPOS_Orders extends Module {
*
* @see Automattic\Jetpack\Sync\Functions::json_wrap as the return value of get_object_vars can vary depending on PHP version.
*/
if ( in_array( $key, array( 'date_created', 'date_modified', 'date_paid', 'date_completed' ), true ) ) {
if ( in_array( $key, array( 'date_created', 'date_modified', 'date_paid', 'date_completed' ), true ) && isset( $order_data[ $key ] ) ) {
if ( is_a( $order_data[ $key ], 'WC_DateTime' ) ) {
$filtered_order_data[ $key ] = (object) (array) $order_data[ $key ];
continue;
@ -327,7 +330,7 @@ class WooCommerce_HPOS_Orders extends Module {
$query = "SELECT count(*) FROM {$this->table_name()} WHERE {$this->get_where_sql( $config ) }";
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Hardcoded query, no user variable
$count = $wpdb->get_var( $query );
$count = (int) $wpdb->get_var( $query );
return (int) ceil( $count / self::ARRAY_CHUNK_SIZE );
}

View File

@ -7,6 +7,7 @@
namespace Automattic\Jetpack\Sync\Modules;
use WC_Order;
use WP_Error;
/**
@ -93,6 +94,9 @@ class WooCommerce extends Module {
// Blacklist Action Scheduler comment types.
add_filter( 'jetpack_sync_prevent_sending_comment_data', array( $this, 'filter_action_scheduler_comments' ), 10, 2 );
// Preprocess action to be sent by Jetpack sync.
add_action( 'woocommerce_remove_order_items', array( $this, 'action_woocommerce_remove_order_items' ), 10, 2 );
}
/**
@ -128,6 +132,7 @@ class WooCommerce extends Module {
add_action( 'woocommerce_new_order_item', $callable, 10, 4 );
add_action( 'woocommerce_update_order_item', $callable, 10, 4 );
add_action( 'woocommerce_delete_order_item', $callable, 10, 1 );
add_action( 'woocommerce_remove_order_item_ids', $callable, 10, 1 );
$this->init_listeners_for_meta_type( 'order_item', $callable );
// Payment tokens.
@ -197,6 +202,25 @@ class WooCommerce extends Module {
return $args;
}
/**
* Retrieve the order item ids to be removed and send them as one action
*
* @param WC_Order $order The order argument.
* @param string $type Order item type.
*/
public function action_woocommerce_remove_order_items( WC_Order $order, $type ) {
if ( $type ) {
$order_items = $order->get_items( $type );
} else {
$order_items = $order->get_items();
}
$order_item_ids = array_keys( $order_items );
if ( $order_item_ids ) {
do_action( 'woocommerce_remove_order_item_ids', $order_item_ids );
}
}
/**
* Expand order item IDs to order items and their meta.
*
@ -269,8 +293,8 @@ class WooCommerce extends Module {
global $wpdb;
$query = "SELECT count(*) FROM $this->order_item_table_name WHERE " . $this->get_where_sql( $config );
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
$count = $wpdb->get_var( $query );
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
$count = (int) $wpdb->get_var( $query );
return (int) ceil( $count / self::ARRAY_CHUNK_SIZE );
}

View File

@ -159,6 +159,7 @@ class Table_Checksum_Usermeta extends Table_Checksum_Users {
*/
protected function expand_and_sanitize_user_meta( $user_object ) {
$user_module = Modules::get_module( 'users' );
'@phan-var \Automattic\Jetpack\Sync\Modules\Users $user_module';
// Expand User Objects based on Sync logic.
$user_object = $user_module->expand_user( $user_object );

View File

@ -242,7 +242,7 @@ class Queue_Storage_Options {
*
* @param int $max_count How many items to fetch from the queue.
*
* @return \stdClass[]|null
* @return object[]|null
*/
public function get_items_ids_with_size( $max_count ) {
global $wpdb;

View File

@ -11,10 +11,18 @@
namespace Automattic\Jetpack\Sync\Queue;
use Automattic\Jetpack\Sync\Sender;
use Automattic\Jetpack\Sync\Settings;
/**
* Custom Sync events table storage backend for the Queue.
*/
class Queue_Storage_Table {
/**
* The name of the transient to use to disable custom queue table in we get a table doesn't exist error.
*/
const CUSTOM_QUEUE_TABLE_DISABLE_WPDB_ERROR_NOT_EXIST_FLAG = 'jetpack_sync_custom_queue_table_disable_wpdb_error_not_exist';
/**
* The custom Sync events table name, without a prefix.
* A prefix will be added when the class is instantiated,
@ -222,7 +230,7 @@ class Queue_Storage_Table {
* @param int|null $item_count How many items to fetch from the queue.
* The parameter is null-able, if no limit on the amount of items.
*
* @return array|object|stdClass[]|null
* @return object[]|null
*/
public function fetch_items( $item_count ) {
global $wpdb;
@ -278,7 +286,7 @@ class Queue_Storage_Table {
*
* @param array $items_ids Items IDs to fetch from the queue.
*
* @return array|object|stdClass[]|null
* @return object[]|null
*/
public function fetch_items_by_ids( $items_ids ) {
global $wpdb;
@ -316,17 +324,33 @@ class Queue_Storage_Table {
global $wpdb;
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
return (int) $wpdb->get_var(
$items_count = (int) $wpdb->get_var(
$wpdb->prepare(
/**
* Ignoring the linting warning, as there's still no placeholder replacement for DB field name,
* in this case this is `$this->table_name`
*/
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
"SELECT count(*) FROM {$this->table_name} WHERE queue_id = %s",
"SELECT COUNT(*) FROM {$this->table_name} WHERE queue_id = %s",
$this->queue_id
)
);
// If the table does not exist, disable the custom queue table and send an error.
if ( ! empty( $wpdb->last_error )
&& str_contains( $wpdb->last_error, $this->table_name_no_prefix . "' doesn't exist" )
&& ! get_transient( self::CUSTOM_QUEUE_TABLE_DISABLE_WPDB_ERROR_NOT_EXIST_FLAG )
) {
set_transient( self::CUSTOM_QUEUE_TABLE_DISABLE_WPDB_ERROR_NOT_EXIST_FLAG, true, 6 * HOUR_IN_SECONDS );
Settings::update_settings( array( 'custom_queue_table_enabled' => 0 ) );
$data = array(
'timestamp' => microtime( true ),
'error' => $wpdb->last_error,
);
$sender = Sender::get_instance();
$sender->send_action( 'jetpack_sync_storage_error_custom_table_not_exist', $data );
}
return $items_count;
}
/**
@ -432,7 +456,7 @@ class Queue_Storage_Table {
*
* @param int $max_count How many items to fetch from the queue.
*
* @return array|object|stdClass[]|null
* @return object[]|null
*/
public function get_items_ids_with_size( $max_count ) {
global $wpdb;
@ -609,6 +633,10 @@ class Queue_Storage_Table {
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$count_result = $wpdb->get_row( "SELECT COUNT(*) as item_count FROM {$custom_table_name}" );
if ( $wpdb->last_error ) {
return;
}
$item_count = $count_result->item_count;
$limit = 100;