PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3-a.7
Jetpack – WP Security, Backup, Speed, & Growth v16.3-a.7
16.3-a.5 16.3-a.7 16.3-a.3 16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 All 506 releases
← All changes | jetpack_vendor/automattic/jetpack-backup/src/class-rest-controller.php +80 -6 13.8.3 → 16.3-a.7 View file →
@@ -9,9 +9,9 @@
9 9 // After changing this file, consider increasing the version number ("VXXX") in all the files using this namespace, in
10 10 // order to ensure that the specific version of this file always get loaded. Otherwise, Jetpack autoloader might decide
11 11 // to load an older/newer version of the class (if, for example, both the standalone and bundled versions of the plugin
12 12 // are installed, or in some other cases).
13 -namespace Automattic\Jetpack\Backup\V0004;
13 +namespace Automattic\Jetpack\Backup\V0005;
14 14
15 15 use Automattic\Jetpack\Connection\Client;
16 16 use Automattic\Jetpack\Connection\Rest_Authentication;
17 17 use Automattic\Jetpack\Sync\Actions as Sync_Actions;
@@ -19,9 +19,8 @@
19 19 use Jetpack_Options;
20 20 use WP_Error;
21 21 use WP_REST_Request;
22 22 use WP_REST_Server;
23 -// phpcs:ignore WordPress.Utils.I18nTextDomainFixer.MissingArgs
24 23 use function esc_html__;
25 24 use function get_comment;
26 25 use function get_comment_meta;
27 26 use function get_metadata;
@@ -34,9 +33,11 @@
34 33 use function is_wp_error;
35 34 use function register_rest_route;
36 35 use function rest_authorization_required_code;
37 36 use function rest_ensure_response;
37 +use function wp_cache_flush;
38 38 use function wp_remote_retrieve_response_code;
39 +use function wp_using_ext_object_cache;
39 40
40 41 /**
41 42 * Registers the REST routes for Backup.
42 43 */
@@ -231,8 +232,19 @@
231 232 'callback' => __CLASS__ . '::get_site_backup_preflight',
232 233 'permission_callback' => __NAMESPACE__ . '\Jetpack_Backup::backups_permissions_callback',
233 234 )
234 235 );
236 +
237 + // Flush the object cache, which a database restore leaves stale.
238 + register_rest_route(
239 + 'jetpack/v4',
240 + '/site/cache/flush',
241 + array(
242 + 'methods' => WP_REST_Server::CREATABLE,
243 + 'callback' => __CLASS__ . '::flush_object_cache',
244 + 'permission_callback' => __CLASS__ . '::backup_permissions_callback',
245 + )
246 + );
235 247 }
236 248
237 249 /**
238 250 * The Backup endpoints should only be available via site-level authentication.
@@ -583,9 +595,13 @@
583 595 null,
584 596 'wpcom'
585 597 );
586 598
587 - if ( 200 !== wp_remote_retrieve_response_code( $response ) ) {
599 + // Cast: `wp_remote_retrieve_response_code()` hands back whatever the
600 + // transport put there, and a numeric-string `'200'` fails this
601 + // strict comparison — so a perfectly good answer is discarded and
602 + // the route reports that the site has no rewindable event to undo.
603 + if ( 200 !== (int) wp_remote_retrieve_response_code( $response ) ) {
588 604 return null;
589 605 }
590 606
591 607 $body = json_decode( $response['body'], true );
@@ -701,9 +717,14 @@
701 717
702 718 /**
703 719 * Fetch backup preflight status
704 720 *
705 - * @return array
721 + * The `array` this used to advertise was never a shape it could return;
722 + * both branches below hand back an object. Corrected because Phan reads
723 + * it, and a caller that believed it would be calling array offsets on a
724 + * `WP_REST_Response`.
725 + *
726 + * @return \WP_REST_Response|WP_Error The preflight payload, or a WP_Error if WordPress.com refused or could not be reached.
706 727 */
707 728 public static function get_site_backup_preflight() {
708 729 $blog_id = Jetpack_Options::get_option( 'id' );
709 730
@@ -722,19 +743,72 @@
722 743 array( 'status' => 500 )
723 744 );
724 745 }
725 746
726 - $response_code = wp_remote_retrieve_response_code( $response );
747 + // Cast and then clamp, and this route needs both more than any
748 + // other in the package. `wp_remote_retrieve_response_code()` hands
749 + // back whatever the transport put there, so an uncast `'200'` fails
750 + // the comparison below — and this is the one place that then
751 + // forwards the status it just read straight into `data.status`.
752 + // WordPress runs that through `absint()`, so the error envelope is
753 + // served as HTTP 200: `apiFetch` resolves, nothing throws, and a
754 + // failure arrives at the caller looking like a successful preflight.
755 + //
756 + // The clamp covers what the cast cannot. `(int)` is total, so an
757 + // absent or unparseable code becomes `0` and `'2 Bad'` becomes `2`,
758 + // and neither is a status `status_header()` can emit. The same
759 + // reasoning, written out at length, is on
760 + // `REST\Rest_Controller::upstream_error()`; it is open-coded here
761 + // rather than borrowed because that helper also attaches
762 + // WordPress.com's own reason under a `wpcom` key, which would change
763 + // this route's response shape for callers we do not control.
764 + $response_code = (int) wp_remote_retrieve_response_code( $response );
727 765 if ( 200 !== $response_code ) {
728 766 return new WP_Error(
729 767 'http_error_fetch_preflight',
730 768 wp_remote_retrieve_response_message( $response ),
731 - array( 'status' => $response_code )
769 + array( 'status' => $response_code >= 400 && $response_code <= 599 ? $response_code : 500 )
732 770 );
733 771 }
734 772
735 773 $body = json_decode( $response['body'], true );
736 774 return rest_ensure_response( $body );
775 + }
776 +
777 + /**
778 + * Flush the object cache.
779 + *
780 + * A database restore writes MySQL directly and never tells WordPress, so
781 + * a site with a persistent cache keeps serving pre-restore rows until
782 + * something busts it.
783 + *
784 + * @access public
785 + * @static
786 + *
787 + * @return \WP_REST_Response Whether the cache was flushed, carrying a `reason` whenever it was not.
788 + */
789 + public static function flush_object_cache() {
790 + if ( ! wp_using_ext_object_cache() ) {
791 + return rest_ensure_response(
792 + array(
793 + 'flushed' => false,
794 + 'reason' => 'no_ext_object_cache',
795 + )
796 + );
797 + }
798 +
799 + // Core documents false as the only failure signal, so a drop-in whose
800 + // flush() returns nothing must not be reported as a failed flush.
801 + if ( false === wp_cache_flush() ) {
802 + return rest_ensure_response(
803 + array(
804 + 'flushed' => false,
805 + 'reason' => 'flush_failed',
806 + )
807 + );
808 + }
809 +
810 + return rest_ensure_response( array( 'flushed' => true ) );
737 811 }
738 812
739 813 /**
740 814 * Fetch option row by option name.