Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
73.68% covered (warning)
73.68%
42 / 57
50.00% covered (danger)
50.00%
1 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
Backup_Sizes_Bridge
76.36% covered (warning)
76.36%
42 / 55
50.00% covered (danger)
50.00%
1 / 2
7.65
0.00% covered (danger)
0.00%
0 / 1
 register_routes
100.00% covered (success)
100.00%
17 / 17
100.00% covered (success)
100.00%
1 / 1
1
 get_backup_sizes
65.79% covered (warning)
65.79%
25 / 38
0.00% covered (danger)
0.00%
0 / 1
7.44
1<?php
2/**
3 * Backup sizes REST bridge — proxies WordPress.com's v3 /sites/{id}/rewind/backups.
4 *
5 * @package automattic/jetpack-backup-plugin
6 */
7
8namespace Automattic\Jetpack\Backup\V0005\REST;
9
10use Automattic\Jetpack\Connection\Client;
11use WP_Error;
12use WP_REST_Request;
13use WP_REST_Server;
14
15if ( ! defined( 'ABSPATH' ) ) {
16    exit( 0 );
17}
18
19/**
20 * Serves each backup's start time and site size, the only per-backup size WordPress.com exposes.
21 */
22class Backup_Sizes_Bridge {
23
24    /**
25     * The most v3 serves per page; above it, it answers a bare `[]`.
26     */
27    const PER_PAGE = 100;
28
29    /**
30     * Register the GET /jetpack/v4/backups/sizes route.
31     *
32     * @return void
33     */
34    public static function register_routes() {
35        register_rest_route(
36            'jetpack/v4',
37            '/backups/sizes',
38            array(
39                'methods'             => WP_REST_Server::READABLE,
40                'callback'            => array( __CLASS__, 'get_backup_sizes' ),
41                'permission_callback' => array( Rest_Controller::class, 'permission_check' ),
42                'args'                => array(
43                    'page' => array(
44                        'description' => __( '1-indexed page number.', 'jetpack-backup-pkg' ),
45                        'type'        => 'integer',
46                        'default'     => 1,
47                        'minimum'     => 1,
48                    ),
49                ),
50            )
51        );
52    }
53
54    /**
55     * Proxy one page of backups, newest first. It refuses blog tokens, so this signs as the user.
56     *
57     * @param WP_REST_Request $request The request.
58     * @return \WP_REST_Response|WP_Error Each backup's `period` and `size` in bytes, or WP_Error on failure.
59     */
60    public static function get_backup_sizes( WP_REST_Request $request ) {
61        $blog_id = Rest_Controller::get_blog_id_or_error();
62        if ( is_wp_error( $blog_id ) ) {
63            return $blog_id;
64        }
65
66        $response = Client::wpcom_json_api_request_as_user(
67            sprintf(
68                '/sites/%d/rewind/backups?number=%d&page=%d',
69                $blog_id,
70                self::PER_PAGE,
71                (int) $request->get_param( 'page' )
72            ),
73            '3',
74            array(),
75            null,
76            'wpcom'
77        );
78
79        if ( is_wp_error( $response ) ) {
80            return Rest_Controller::transport_error( $response, 'backup_sizes_fetch_failed' );
81        }
82
83        if ( 200 !== (int) wp_remote_retrieve_response_code( $response ) ) {
84            return Rest_Controller::upstream_error(
85                $response,
86                'backup_sizes_fetch_failed',
87                __( 'Could not fetch the size of each backup.', 'jetpack-backup-pkg' )
88            );
89        }
90
91        $decoded = json_decode( wp_remote_retrieve_body( $response ), true );
92        $backups = array();
93
94        // Only what the dashboard reads: `backup_stats` alone lists every plugin and table.
95        foreach ( (array) ( $decoded['backups'] ?? array() ) as $backup ) {
96            if ( ! isset( $backup['object']['backup_period'] ) ) {
97                continue;
98            }
99            $backups[] = array(
100                'period' => (int) $backup['object']['backup_period'],
101                'size'   => (int) ( $backup['object']['backup_size'] ?? 0 ),
102            );
103        }
104
105        return rest_ensure_response(
106            array(
107                'totalPages' => (int) ( $decoded['totalPages'] ?? 0 ),
108                'backups'    => $backups,
109            )
110        );
111    }
112}