Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
48.00% covered (danger)
48.00%
24 / 50
40.00% covered (danger)
40.00%
4 / 10
CRAP
0.00% covered (danger)
0.00%
0 / 1
Playground_Importer
57.14% covered (warning)
57.14%
24 / 42
40.00% covered (danger)
40.00%
4 / 10
39.75
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 get_sqlite_db_path
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 find_sqlite_db_path
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
4
 preprocess
75.00% covered (warning)
75.00%
9 / 12
0.00% covered (danger)
0.00%
0 / 1
3.14
 process_files
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
12
 recreate_database
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 postprocess_database
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 clean_up
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 verify_site_integrity
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 is_valid
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2/**
3 * Playground_Importer file.
4 *
5 * @package wpcomsh
6 */
7
8namespace Imports;
9
10require_once __DIR__ . '/../class-backup-importer.php';
11require_once __DIR__ . '/class-playground-db-importer.php';
12require_once __DIR__ . '/class-playground-clean-up.php';
13require_once __DIR__ . '/class-sql-importer.php';
14require_once __DIR__ . '/../utils/class-filerestorer.php';
15require_once __DIR__ . '/../utils/logger/class-filelogger.php';
16require_once __DIR__ . '/class-sql-postprocessor.php';
17require_once __DIR__ . '/class-playground-site-integrity-check.php';
18
19use Imports\Utils\FileRestorer;
20use Imports\Utils\Logger\FileLogger;
21
22/**
23 * Playground backup importer.
24 *
25 * This class provides a common interface for all backup importers.
26 */
27class Playground_Importer extends \Imports\Backup_Importer {
28    const SQLITE_DB_PATH = 'wp-content/database/.ht.sqlite';
29
30    /**
31     * File logger
32     *
33     * @var FileLogger
34     */
35    private FileLogger $logger;
36
37    /**
38     * Constructor.
39     *
40     * @param string $zip_or_tar_file_path The path to the ZIP or TAR file to be imported.
41     * @param string $destination_path The path where the backup will be imported.
42     * @param string $tmp_prefix       The table prefix to use when importing the database.
43     */
44    public function __construct( string $zip_or_tar_file_path, string $destination_path, string $tmp_prefix ) {
45        parent::__construct( $zip_or_tar_file_path, $destination_path, $tmp_prefix );
46
47        $this->logger = new FileLogger();
48        $this->logger->check_and_clear_file();
49
50        $this->tmp_database = $this->destination_path . 'database.sql';
51    }
52
53    /**
54     * Get the path to the SQLite database file.
55     *
56     * @return string|null The path to the SQLite database file, or null if none is found.
57     */
58    public function get_sqlite_db_path(): ?string {
59        return self::find_sqlite_db_path( $this->destination_path );
60    }
61
62    /**
63     * Find the SQLite database file inside an extracted backup.
64     *
65     * The SQLite database file is located at `wp-content/database/.ht.sqlite` or in a folder of the
66     * type `wp-content/database/.ht.<random>/.ht.sqlite`.
67     *
68     * @param string $destination_path The path where the backup was extracted.
69     *
70     * @return string|null The path to the SQLite database file, or null if none is found.
71     */
72    private static function find_sqlite_db_path( string $destination_path ): ?string {
73        $destination_path = trailingslashit( $destination_path );
74        $default_path     = $destination_path . self::SQLITE_DB_PATH;
75        if ( file_exists( $default_path ) ) {
76            return $default_path;
77        }
78
79        $matches = glob( $destination_path . 'wp-content/database/.ht.*/.ht.sqlite' );
80        foreach ( (array) $matches as $path ) {
81            if ( file_exists( $path ) ) {
82                return $path;
83            }
84        }
85
86        return null;
87    }
88
89    /**
90     * Preprocess the backup before importing.
91     *
92     * @return bool|\WP_Error True on success, or a WP_Error on failure.
93     */
94    public function preprocess() {
95        $options = array(
96            'output_mode' => SQL_Generator::OUTPUT_TYPE_FILE,
97            'output_file' => $this->tmp_database,
98            'tmp_tables'  => true,
99            'tmp_prefix'  => $this->tmp_prefix,
100        );
101        $db_path = $this->get_sqlite_db_path();
102        if ( null === $db_path ) {
103            return new \WP_Error( 'database-file-not-exists', 'Database file not exists' );
104        }
105
106        $importer = new Playground_DB_Importer();
107        $results  = $importer->generate_sql( $db_path, $options );
108
109        return is_wp_error( $results ) ? $results : true;
110    }
111
112    /**
113     * Process the files in the backup.
114     *
115     * @return bool|\WP_Error True on success, or a WP_Error on failure.
116     */
117    public function process_files() {
118        $final_path    = '/srv/htdocs/';
119        $file_restorer = new FileRestorer( $this->destination_path, $final_path, $this->logger );
120        $queue_result  = $file_restorer->enqueue_files();
121
122        if ( is_wp_error( $queue_result ) ) {
123            return $queue_result;
124        }
125
126        $restore_result = $file_restorer->restore_files();
127
128        if ( is_wp_error( $restore_result ) ) {
129            return $restore_result;
130        }
131
132        return true;
133    }
134
135    /**
136     * Recreate the database from the backup.
137     *
138     * @return bool|\WP_Error True on success, or a WP_Error on failure.
139     */
140    public function recreate_database() {
141        return SQL_Importer::import( $this->tmp_database );
142    }
143
144    /**
145     * Postprocess the database after importing.
146     *
147     * @return bool|\WP_Error True on success, or a WP_Error on failure.
148     */
149    public function postprocess_database() {
150        $processor = new SQL_Postprocessor( get_home_url(), get_site_url(), $this->tmp_prefix, false, $this->logger );
151
152        return $processor->postprocess();
153    }
154
155    /**
156     * Clean up after the import.
157     *
158     * @return bool|\WP_Error True on success, or a WP_Error on failure.
159     */
160    public function clean_up() {
161        return Playground_Clean_Up::remove_tmp_files( $this->zip_or_tar_file_path, $this->destination_path );
162    }
163
164    /**
165     * Verify the integrity of the site after importing.
166     *
167     * @return bool always true for now
168     */
169    public function verify_site_integrity() {
170        $checker = new Playground_Site_Integrity_Check( $this->logger );
171        return $checker->check();
172    }
173
174    /**
175     * Return whether the specified folder is a valid Playground backup.
176     *
177     * @param string $destination_path The path where the backup will be imported.
178     *
179     * @return bool True if the specified folder is a valid backup, false otherwise.
180     */
181    public static function is_valid( $destination_path ): bool {
182        return self::find_sqlite_db_path( $destination_path ) !== null;
183    }
184}