PluginProbe ʕ •ᴥ•ʔ
WP STAGING – WordPress Backups, Restore, Migration & Clone / 4.11.0
WP STAGING – WordPress Backups, Restore, Migration & Clone v4.11.0
4.11.0 4.10.0 4.9.5 4.9.4 4.9.3 4.9.2 4.9.1 4.9.0 4.8.1 trunk 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.1.0 3.1.1 3.1.2 3.1.3 3.1.4 3.10.0 3.2.0 3.3.1 3.3.2 3.3.3 3.4.1 3.4.3 3.5.0 3.6.0 3.7.1 3.8.0 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.8.6 3.8.7 3.9.0 3.9.1 3.9.2 3.9.3 3.9.4 4.0.0 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 4.2.0 4.2.1 4.3.0 4.3.1 4.3.2 4.4.0 4.5.0 4.6.0 4.7.0 4.7.1 4.7.2 4.7.3 4.8.0
wp-staging / Staging / Ajax / Create / PrepareCreate.php
wp-staging / Staging / Ajax / Create Last commit date
PrepareCreate.php 1 day ago
PrepareCreate.php
289 lines
1 <?php
2
3 namespace WPStaging\Staging\Ajax\Create;
4
5 use WPStaging\Core\WPStaging;
6 use WPStaging\Framework\Facades\Sanitize;
7 use WPStaging\Framework\Job\JobTransientCache;
8 use WPStaging\Staging\Ajax\AbstractAjaxPrepare;
9 use WPStaging\Staging\Dto\Job\StagingSiteJobsDataDto;
10 use WPStaging\Staging\Dto\StagingSiteDto;
11 use WPStaging\Staging\Jobs\StagingSiteCreate;
12 use WPStaging\Staging\Service\StagingEngine;
13 use WPStaging\Staging\Service\StagingSetup;
14 use WPStaging\Staging\Sites;
15
16 class PrepareCreate extends AbstractAjaxPrepare
17 {
18
19 protected $postDataKey = 'wpstgCreateData';
20
21
22 protected $jobDataDto;
23
24
25 protected $jobCreate;
26
27 protected function postDataSanitization(): array
28 {
29 if (empty($_POST['wpstgCreateData'])) {
30 throw new \UnexpectedValueException("Invalid request. Missing 'wpstgCreateData'. Should never happen.");
31 }
32
33 $data = Sanitize::sanitizeArray($_POST['wpstgCreateData'], [
34 'cloneId' => 'string',
35 'stagingEngine' => 'string',
36 'allTablesExcluded' => 'bool',
37 'excludeSizeGreaterThan' => 'string',
38 ]);
39
40 $data['name'] = isset($_POST['wpstgCreateData']['name']) ? Sanitize::sanitizeString($_POST['wpstgCreateData']['name']) : '';
41 $data['excludedTables'] = isset($_POST['wpstgCreateData']['excludedTables']) ? $this->parseAndSanitizeTables($_POST['wpstgCreateData']['excludedTables']) : []; // phpcs:ignore
42 $data['includedTables'] = isset($_POST['wpstgCreateData']['includedTables']) ? $this->parseAndSanitizeTables($_POST['wpstgCreateData']['includedTables']) : []; // phpcs:ignore
43 $data['nonSiteTables'] = isset($_POST['wpstgCreateData']['nonSiteTables']) ? $this->parseAndSanitizeTables($_POST['wpstgCreateData']['nonSiteTables']) : []; // phpcs:ignore
44 $data['excludedDirectories'] = isset($_POST['wpstgCreateData']['excludedDirectories']) ? $this->parseAndSanitizeDirectories($_POST['wpstgCreateData']['excludedDirectories']) : []; // phpcs:ignore
45 $data['extraDirectories'] = isset($_POST['wpstgCreateData']['extraDirectories']) ? $this->parseAndSanitizeDirectories($_POST['wpstgCreateData']['extraDirectories']) : []; // phpcs:ignore
46
47 $data['excludeFileRules'] = isset($_POST['wpstgCreateData']['excludeFileRules']) ? $this->parseAndSanitizeDirectories($_POST['wpstgCreateData']['excludeFileRules']) : []; // phpcs:ignore
48 $data['excludeFolderRules'] = isset($_POST['wpstgCreateData']['excludeFolderRules']) ? $this->parseAndSanitizeDirectories($_POST['wpstgCreateData']['excludeFolderRules']) : []; // phpcs:ignore
49 $data['excludeExtensionRules'] = isset($_POST['wpstgCreateData']['excludeExtensionRules']) ? $this->parseAndSanitizeDirectories($_POST['wpstgCreateData']['excludeExtensionRules']) : []; // phpcs:ignore
50 $data = array_merge($data, $this->getAdvanceSettings());
51
52 return $data;
53 }
54
55 protected function additionalSanitization(array $data): array
56 {
57
58 $data['cloneId'] = sanitize_text_field($data['cloneId']);
59 $data['stagingEngine'] = StagingEngine::ENGINE_NEXT_GEN;
60
61 if (empty($data['cloneId'])) {
62 throw new \UnexpectedValueException("Invalid request. Missing 'cloneId'.");
63 }
64
65 $data['name'] = empty($data['name']) ? $this->generateStagingSiteName($data['cloneId']) : sanitize_text_field($data['name']);
66 $data['directoryName'] = $this->sanitizeDirectoryName($data['name'], $data['cloneId']);
67
68
69 $data['excludedTables'] = array_map('sanitize_text_field', $data['excludedTables']);
70 $data['includedTables'] = array_map('sanitize_text_field', $data['includedTables']);
71 $data['nonSiteTables'] = array_map('sanitize_text_field', $data['nonSiteTables']);
72
73
74 $data['extraDirectories'] = array_map('sanitize_text_field', $data['extraDirectories']);
75 $data['excludedDirectories'] = array_map('sanitize_text_field', $data['excludedDirectories']);
76
77
78 $data['excludeSizeGreaterThan'] = sanitize_text_field($data['excludeSizeGreaterThan']);
79 $data['excludeFileRules'] = array_map('sanitize_text_field', $data['excludeFileRules']);
80 $data['excludeFolderRules'] = array_map('sanitize_text_field', $data['excludeFolderRules']);
81 $data['excludeExtensionRules'] = array_map('sanitize_text_field', $data['excludeExtensionRules']);
82
83 $data = $this->validateAndSanitizeAdvanceSettingsData($data);
84
85 $data['stagingSitePath'] = $this->getDestinationPath($data);
86 $data['stagingSiteUrl'] = $this->getDestinationUrl($data);
87
88 return $data;
89 }
90
91 protected function getDefaults(): array
92 {
93 return [
94 'cloneId' => time(),
95 'stagingEngine' => StagingEngine::ENGINE_NEXT_GEN,
96 'name' => '',
97 'allTablesExcluded' => false,
98 'excludedTables' => [],
99 'includedTables' => [],
100 'nonSiteTables' => [],
101 'excludedDirectories' => [],
102 'extraDirectories' => [],
103
104 'excludeSizeGreaterThan' => 8,
105 'excludeFileRules' => [],
106 'excludeFolderRules' => [],
107 'excludeExtensionRules' => [],
108 ];
109 }
110
111 protected function getAdvanceSettings(): array
112 {
113 return [];
114 }
115
116 protected function validateAndSanitizeAdvanceSettingsData(array $data): array
117 {
118
119 $data['useNewAdminAccount'] = false;
120 $data['adminEmail'] = '';
121 $data['adminPassword'] = '';
122
123
124 $data['useCustomDatabase'] = false;
125 $data['databaseServer'] = '';
126 $data['databaseName'] = '';
127 $data['databaseUser'] = '';
128 $data['databasePassword'] = '';
129 $data['databasePrefix'] = '';
130 $data['databaseSsl'] = false;
131
132
133 $data['customPath'] = '';
134 $data['customUrl'] = '';
135
136
137 $data['isEmailsAllowed'] = true;
138 $data['isUploadsSymlinked'] = false;
139 $data['isCronEnabled'] = true;
140 $data['isWooSchedulerEnabled'] = true;
141 $data['isEmailsReminderEnabled'] = false;
142 $data['isAutoUpdatePlugins'] = false;
143
144 return $data;
145 }
146
147
148
149
150
151 protected function setupInitialData($sanitizedData): array
152 {
153 $sanitizedData = $this->validateAndSanitizeData($sanitizedData);
154 $this->clearCacheFolder();
155
156
157 $services = WPStaging::getInstance()->getContainer();
158
159 $this->jobDataDto = $services->get(StagingSiteJobsDataDto::class);
160
161 $this->jobCreate = $services->get($this->getJobClass());
162
163 $this->jobDataDto->hydrate($sanitizedData);
164 $this->jobDataDto->setInit(true);
165 $this->jobDataDto->setFinished(false);
166 $this->jobDataDto->setStartTime(time());
167 $this->jobDataDto->setStagingSiteUploads($this->directory->getRelativeUploadsDirectory());
168 $this->jobDataDto->setJobType(StagingSetup::JOB_NEW_STAGING_SITE);
169
170 $this->prepareStagingSiteDto();
171
172 $this->jobDataDto->setId(substr(md5(mt_rand() . time()), 0, 12));
173
174 $this->jobCreate->getTransientCache()->startJob($this->jobDataDto->getId(), esc_html__('Cloning in Progress', 'wp-staging'), JobTransientCache::JOB_TYPE_STAGING_CREATE, $this->queueId);
175
176 $this->jobCreate->setJobDataDto($this->jobDataDto);
177
178 return $sanitizedData;
179 }
180
181
182
183
184
185
186 public function getJob()
187 {
188 return $this->jobCreate;
189 }
190
191
192
193
194 protected function getJobClass(): string
195 {
196 return StagingSiteCreate::class;
197 }
198
199
200
201
202
203
204 public function persist(): bool
205 {
206 if (!$this->jobCreate instanceof StagingSiteCreate) {
207 return false;
208 }
209
210 $this->jobCreate->persist();
211
212 return true;
213 }
214
215 protected function findDatabasePrefix()
216 {
217 global $wpdb;
218
219
220
221 for ($i = 0; $i <= 10000; $i++) {
222 $prefix = 'wpstg' . $i . '_';
223
224 $sql = "SHOW TABLE STATUS LIKE '{$prefix}%'";
225 $tables = $wpdb->get_results($sql);
226
227
228 if (!$tables) {
229 return $prefix;
230 }
231 }
232 }
233
234 protected function generateStagingSiteName(string $cloneId): string
235 {
236 return WPStaging::make(Sites::class)->generateStagingSiteName($cloneId);
237 }
238
239
240
241
242
243
244
245
246 protected function sanitizeDirectoryName(string $name, string $cloneId): string
247 {
248 $name = preg_replace('#[^\w\s-]+#', '', $name);
249 $directoryName = trim(WPStaging::make(Sites::class)->sanitizeDirectoryName($name), '-');
250 if (empty($directoryName)) {
251 return $this->generateStagingSiteName($cloneId);
252 }
253
254 return $directoryName;
255 }
256
257 protected function prepareStagingSiteDto()
258 {
259 $this->jobDataDto->setIsExternalDatabase(false);
260 $this->jobDataDto->setDatabasePrefix($this->findDatabasePrefix());
261
262 $stagingSite = new StagingSiteDto();
263 $stagingSite->setCloneId($this->jobDataDto->getCloneId());
264 $stagingSite->setCloneName($this->jobDataDto->getName());
265 $stagingSite->setDirectoryName($this->jobDataDto->getDirectoryName());
266 $stagingSite->setPath($this->jobDataDto->getStagingSitePath());
267 $stagingSite->setUrl($this->jobDataDto->getStagingSiteUrl());
268 $stagingSite->setStatus(StagingSiteDto::STATUS_UNFINISHED_BROKEN);
269 $stagingSite->setPrefix($this->jobDataDto->getDatabasePrefix());
270 $stagingSite->setDatetime(time());
271 $stagingSite->setVersion(WPStaging::getVersion());
272 $stagingSite->setOwnerId(get_current_user_id());
273
274 $this->jobDataDto->setStagingSite($stagingSite);
275 }
276
277 protected function getDestinationPath(array $data): string
278 {
279 $absPath = trailingslashit($this->filesystem->normalizePath($this->directory->getAbsPath()));
280
281 return $absPath . $data['directoryName'];
282 }
283
284 protected function getDestinationUrl(array $data): string
285 {
286 return trailingslashit(home_url()) . $data['directoryName'];
287 }
288 }
289