Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 77
0.00% covered (danger)
0.00%
0 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
Backup_Import_Response
0.00% covered (danger)
0.00%
0 / 77
0.00% covered (danger)
0.00%
0 / 6
272
0.00% covered (danger)
0.00%
0 / 1
 register_routes
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
2
 verify_import_permissions
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 get_backup_import_status
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
30
 reset_backup_import_status
0.00% covered (danger)
0.00%
0 / 30
0.00% covered (danger)
0.00%
0 / 1
20
 verify_xml_rpc_signature
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
6
 read_last_log_line
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2/**
3 * Backup Import handler.
4 *
5 * @package endpoints
6 */
7
8use Imports\Backup_Import_Manager;
9
10/**
11 * Backup Import response endpoint.
12 *
13 * @package endpoints
14 */
15class Backup_Import_Response extends WP_REST_Controller {
16    /**
17     * The API namespace.
18     *
19     * @var string
20     */
21    protected $namespace = 'wpcomsh/v1';
22
23    /**
24     * The API REST base URL.
25     *
26     * @var string
27     */
28    protected $rest_base = 'backup-import';
29
30    /**
31     * Registers the routes for the objects of the controller.
32     */
33    public function register_routes() {
34        // GET https://<atomic-site-address>/wp-json/wpcomsh/v1/backup-import/status.
35        register_rest_route(
36            $this->namespace,
37            '/' . $this->rest_base . '/status',
38            array(
39                'methods'             => WP_REST_Server::READABLE,
40                'callback'            => array( $this, 'get_backup_import_status' ),
41                'permission_callback' => array( $this, 'verify_xml_rpc_signature' ),
42            )
43        );
44
45        // POST https://<atomic-site-address>/wp-json/wpcomsh/v1/backup-import/status.
46        register_rest_route(
47            $this->namespace,
48            '/' . $this->rest_base . '/status',
49            array(
50                'methods'             => WP_REST_Server::CREATABLE,
51                'callback'            => array( $this, 'reset_backup_import_status' ),
52                'permission_callback' => array( $this, 'verify_xml_rpc_signature' ),
53            )
54        );
55    }
56
57    /**
58     * Only users with import access can do the action.
59     *
60     * @return bool
61     */
62    public function verify_import_permissions() {
63        return current_user_can( 'import' );
64    }
65
66    /**
67     * Gets the backup import status.
68     *
69     * @param WP_REST_Request $request Full details about the request.
70     * @return WP_REST_Response Returns a WP_REST_Response with the backup import status.
71     */
72    public function get_backup_import_status( $request ) { //phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter, VariableAnalysis.CodeAnalysis.VariableAnalysis
73        if ( ! $this->verify_import_permissions() ) {
74            return new WP_REST_Response(
75                array(
76                    'error' => 'User or Token does not have access to specified site.',
77                ),
78                400
79            );
80        }
81
82        $backup_import_status = Backup_Import_Manager::get_backup_import_status();
83        $message              = '';
84
85        if ( $backup_import_status && $backup_import_status['status'] === 'process_files' ) {
86            // Read the log file and return last line of the log
87            $message = $this->read_last_log_line();
88        }
89
90        return new WP_REST_Response(
91            array(
92                'status'  => $backup_import_status ? $backup_import_status['status'] : '',
93                'message' => $message,
94            ),
95            200
96        );
97    }
98
99    /**
100     * Resets the backup import status.
101     *
102     * @return WP_REST_Response Returns a WP_REST_Response with either a success message or an error message.
103     */
104    public function reset_backup_import_status() {
105        if ( ! $this->verify_import_permissions() ) {
106            return new WP_REST_Response(
107                array(
108                    'error' => 'User or Token does not have access to specified site.',
109                ),
110                400
111            );
112        }
113
114        $backup_import_status = Backup_Import_Manager::get_backup_import_status();
115
116        if ( empty( $backup_import_status ) ) {
117            return new WP_REST_Response(
118                array(
119                    'error' => 'No backup import found.',
120                ),
121                400
122            );
123        }
124        $result = Backup_Import_Manager::reset_import_status();
125
126        if ( is_wp_error( $result ) ) {
127            return new WP_REST_Response(
128                array(
129                    'error' => $result->get_error_message(),
130                ),
131                400
132            );
133        }
134
135        return new WP_REST_Response(
136            array(
137                'success' => true,
138                'message' => 'Reset backup import status successfully.',
139            ),
140            200
141        );
142    }
143
144    /**
145     * Checks if a given request has the correct signature. We only
146     * want to accept "internal" requests from WPCOM.
147     *
148     * @param WP_REST_Request $request Full details about the request.
149     * @return bool True if the request has access, false otherwise.
150     */
151    public function verify_xml_rpc_signature( $request ) { //phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass, VariableAnalysis.CodeAnalysis.VariableAnalysis
152        return method_exists( 'Automattic\Jetpack\Connection\Manager', 'verify_xml_rpc_signature' ) && ( new Automattic\Jetpack\Connection\Manager() )->verify_xml_rpc_signature();
153    }
154
155    /**
156     * Reads the last line of the log file.
157     *
158     * @return string|null The last line of the log file, or null if the file could not be read.
159     */
160    public function read_last_log_line() {
161        $log_file = '/tmp/restore_log/restoration_log.txt';
162        if ( ! file_exists( $log_file ) ) {
163            return null;
164        }
165
166        $log_lines = file( $log_file, FILE_IGNORE_NEW_LINES );
167        $last_line = end( $log_lines );
168
169        // Find the position of the first space after the timestamp
170        $pos = strpos( $last_line, ' ' );
171
172        // If a space was found, return the part of the string after it
173        if ( $pos !== false ) {
174            return substr( $last_line, $pos + 1 );
175        }
176
177        // If no space was found, return the whole line
178        return $last_line;
179    }
180}