PluginProbe
WP Synchro – The Ultimate WordPress Migration Tool / trunk
WP Synchro – The Ultimate WordPress Migration Tool vtrunk
1.16.1 1.16.0 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.1.0 1.10.0 1.11.0 1.11.1 1.11.2 1.11.3 1.11.4 1.11.5 1.12.0 1.13.0 1.14.0 1.15.0 1.2.0 1.3.0 1.3.1 1.3.2 All 45 releases
wpsynchro / src / API / DatabaseBackup.php

DatabaseBackup.php in WP Synchro – The Ultimate WordPress Migration Tool trunk, at src/API/DatabaseBackup.php

193 lines 6.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace WPSynchro\API;
4
5 use WPSynchro\Database\DatabaseHelperFunctions;
6 use WPSynchro\Database\DatabaseSync;
7 use WPSynchro\Migration\Job;
8 use WPSynchro\Transport\ReturnResult;
9 use WPSynchro\Transport\Transfer;
10 use WPSynchro\Transport\TransferAccessKey;
11 use WPSynchro\Utilities\PluginDirs;
12
13 /**
14 * Class for handling service to backup database
15 * Call should already be verified by permissions callback
16 *
17 */
18 class DatabaseBackup extends WPSynchroService
19 {
20 public function service()
21 {
22 $transfer = new Transfer();
23 $transfer->setEncryptionKey(TransferAccessKey::getAccessKey());
24 $transfer->populateFromString($this->getRequestBody());
25 $body = $transfer->getDataObject();
26
27 /**
28 * Extract parameters
29 */
30 $data_required_errors = false;
31
32 if (isset($body->table)) {
33 $table = $body->table;
34 } else {
35 $data_required_errors = true;
36 }
37
38 if (isset($body->filename)) {
39 $filename = $body->filename;
40 $plugins_dirs = new PluginDirs();
41 $filepath = $plugins_dirs->getUploadsFilePath() . $filename;
42 } else {
43 $data_required_errors = true;
44 }
45 if (isset($body->memory_limit)) {
46 $memory_limit = $body->memory_limit;
47 } else {
48 $data_required_errors = true;
49 }
50 if (isset($body->time_limit)) {
51 $time_limit = $body->time_limit;
52 } else {
53 $data_required_errors = true;
54 }
55
56 if ($data_required_errors) {
57 $returnresult = new ReturnResult();
58 $returnresult->init();
59 $returnresult->setHTTPStatus(400);
60 return $returnresult->echoDataFromServiceAndExit();
61 }
62
63 $result = new \stdClass();
64 $result->errors = [];
65 $result->warnings = [];
66 $result->debugs = [];
67 $result->infos = [];
68
69 // Add location to log file
70 $result->infos[] = "Database backup is written to " . $filepath . " on site " . get_home_url();
71
72 /**
73 * Get started with the export
74 */
75 // Calculate rows to go for
76 if ($table->row_avg_bytes > 0) {
77 $rows_per_run = ceil((1024 * 1024) / $table->row_avg_bytes);
78 } else {
79 $rows_per_run = 9900;
80 }
81
82 $database_helper_functions = new DatabaseHelperFunctions();
83 $one_mb = 1024 * 1024;
84
85 $data_result_from_db = $database_helper_functions->getDataFromDB(
86 $table->name,
87 $table->getColumnNames(),
88 $table->primary_key_column,
89 $table->last_primary_key,
90 $table->completed_rows,
91 $one_mb,
92 $rows_per_run,
93 $time_limit
94 );
95
96 $data = $data_result_from_db->data;
97 $result->has_more_rows_in_table = $data_result_from_db->has_more_rows_in_table;
98 $result->errors = array_merge($result->errors, $data_result_from_db->errors);
99
100 // Get databasesync object
101 $databasesync = new DatabaseSync();
102 $databasesync->job = new Job();
103 $databasesync->job->warnings = &$result->warnings;
104 $databasesync->job->masterdata_max_memory_limit_bytes = $memory_limit;
105
106 // Check if there is more than X backups and delete the oldest, this needs to be done before the first data is written to file - should only run once
107 if (!file_exists($filepath)) {
108 $dir = dirname($filepath);
109 $this->deleteOldBackups($dir);
110 }
111
112 // Add create table to sql file
113 if ($table->completed_rows == 0) {
114 $file_append_create_table = file_put_contents($filepath, PHP_EOL . $table->create_table . ";" . PHP_EOL, FILE_APPEND);
115 if ($file_append_create_table === false) {
116 // translators: %s is replaced with file path to database backup
117 $result->errors[] = sprintf(__("Appending create table for database backup to %s failed.", "wpsynchro"), $filepath);
118 } else {
119 $result->debugs[] = "Wrote create table data for table " . $table->name;
120 }
121 }
122
123 // If rows fetched less than max rows, than mark table as completed
124 if (!$result->has_more_rows_in_table) {
125 $table->completed_rows = $table->rows;
126 }
127
128 // If any rows, get the insert sql version and insert into file
129 $rows_fetched = count($data);
130 if ($rows_fetched > 0) {
131 $sql_inserts = ["SET FOREIGN_KEY_CHECKS=0"];
132 $sql_inserts = array_merge($sql_inserts, $databasesync->generateSQLInserts($table, $data, (200 * 1024 * 1024)));
133
134 foreach ($sql_inserts as &$sqlinsert) {
135 $sqlinsert .= ";" . PHP_EOL;
136 }
137
138 // Write to sql file
139 $file_append_result = file_put_contents($filepath, $sql_inserts, FILE_APPEND);
140 if ($file_append_result === false) {
141 // translators: %s is replaced with file path to database backup
142 $result->errors[] = sprintf(__("Appending databasebackup to %s failed.", "wpsynchro"), $filepath);
143 } else {
144 $result->debugs[] = "Wrote data for table " . $table->name;
145 }
146
147 if ($table->completed_rows < $table->rows) {
148 $table->completed_rows += $rows_fetched;
149 }
150 }
151
152 $result->table = $table;
153
154 $returnresult = new ReturnResult();
155 $returnresult->init();
156 $returnresult->setDataObject($result);
157 return $returnresult->echoDataFromServiceAndExit();
158 }
159
160 /**
161 * Delete backup files, if needed, based on the configuration
162 */
163 public function deleteOldBackups($path)
164 {
165 // Get files ending with sql
166 $files = [];
167 foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, \FilesystemIterator::SKIP_DOTS)) as $value) {
168 if ($value->isFile() && strtolower($value->getExtension()) === 'sql') {
169 $files[] = [$value->getMTime(), $value->getRealPath()];
170 }
171 }
172
173 // If more than 19, aka 20 or above, delete the oldest
174 if (count($files) > 19) {
175 // Sort by timestamp
176 usort($files, function ($a, $b) {
177 if ($a[0] == $b[0]) {
178 return 0;
179 }
180 return $a[0] > $b[0] ? 1 : -1;
181 });
182
183 // Remove the last 19 we want to keep
184 array_splice($files, count($files) - 19, 19);
185
186 // Delete the other files
187 foreach ($files as $file) {
188 @unlink($file[1]);
189 }
190 }
191 }
192 }
193