PluginProbe ʕ •ᴥ•ʔ
WP STAGING – WordPress Backups, Restore, Migration & Clone / 4.10.0
WP STAGING – WordPress Backups, Restore, Migration & Clone v4.10.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 / Framework / Onboarding / OnboardingAjax.php
wp-staging / Framework / Onboarding Last commit date
BackupPluginsDetector.php 5 days ago FirstInstall.php 5 days ago FreeOnboarding.php 5 days ago NextStepRenderer.php 5 days ago OnboardingAjax.php 5 days ago OnboardingJourney.php 5 days ago QueuedBackup.php 5 days ago
OnboardingAjax.php
236 lines
1 <?php
2
3 namespace WPStaging\Framework\Onboarding;
4
5 use WPStaging\Framework\Security\Auth;
6 use WPStaging\Framework\Utils\Sanitize;
7
8 /**
9 * Endpoints the first run calls as the user picks an action, watches it start,
10 * parks a backup for after the staging site, or leaves the journey.
11 */
12 class OnboardingAjax
13 {
14 /** @var Auth */
15 private $auth;
16
17 /** @var Sanitize */
18 private $sanitize;
19
20 /** @var FreeOnboarding */
21 private $onboarding;
22
23 /** @var QueuedBackup */
24 private $queuedBackup;
25
26 /** @var OnboardingJourney */
27 private $journey;
28
29 public function __construct(
30 Auth $auth,
31 Sanitize $sanitize,
32 FreeOnboarding $onboarding,
33 QueuedBackup $queuedBackup,
34 OnboardingJourney $journey
35 ) {
36 $this->auth = $auth;
37 $this->sanitize = $sanitize;
38 $this->onboarding = $onboarding;
39 $this->queuedBackup = $queuedBackup;
40 $this->journey = $journey;
41 }
42
43 public function ajaxSelectAction()
44 {
45 if (!$this->isAuthorized()) {
46 return;
47 }
48
49 if (!$this->onboarding->selectAction($this->postValue('onboardingAction'))) {
50 wp_send_json_error(null, 400);
51 return;
52 }
53
54 wp_send_json_success();
55 }
56
57 /**
58 * The job behind the chosen action has begun, which is what a later success
59 * gets matched against.
60 */
61 public function ajaxActionStarted()
62 {
63 if (!$this->isAuthorized()) {
64 return;
65 }
66
67 $this->journey->startAction();
68
69 wp_send_json_success();
70 }
71
72 public function ajaxOfferShown()
73 {
74 if (!$this->isAuthorized()) {
75 return;
76 }
77
78 $this->journey->recordNextOfferShown(OnboardingJourney::SURFACE_STAGING_PROGRESS);
79
80 wp_send_json_success();
81 }
82
83 /**
84 * Puts the first run back on screen, for the footer link in debug builds.
85 *
86 * @return void
87 */
88 public function ajaxRestart()
89 {
90 if (!$this->isAuthorized()) {
91 return;
92 }
93
94 if (!$this->onboarding->canRestart()) {
95 wp_send_json_error(null, 403);
96 return;
97 }
98
99 $this->onboarding->restart();
100
101 wp_send_json_success();
102 }
103
104 /**
105 * The state that follows a completed capability, rendered now rather than
106 * when the page loaded.
107 *
108 * @return void
109 */
110 public function ajaxNextStep()
111 {
112 if (!$this->isAuthorized()) {
113 return;
114 }
115
116 $renderer = NextStepRenderer::resolve();
117
118 wp_send_json_success(['html' => $renderer === null ? '' : $renderer->render()]);
119 }
120
121 /**
122 * How the backup parked behind the staging site is doing, for a user who
123 * stayed on the screen that started it.
124 *
125 * @return void
126 */
127 public function ajaxQueuedBackupStatus()
128 {
129 if (!$this->isAuthorized()) {
130 return;
131 }
132
133 // Before answering: the request that asks how the backup is doing is also
134 // the one that can get it moving, and on a server that cannot call itself
135 // nothing else will for another minute.
136 $this->queuedBackup->runWaitingWork();
137
138 $status = $this->queuedBackup->getReportedStatus();
139
140 wp_send_json_success([
141 'status' => $status,
142 'panel' => $this->shouldRenderJobPanel($status) ? $this->renderJobPanel() : '',
143 ]);
144 }
145
146 /**
147 * The screen asks for the job panel because the card could not carry one: it
148 * is rendered the moment the staging site finishes, and the backup released
149 * behind it is queued rather than running until background processing picks
150 * it up, which can be a while after.
151 */
152 private function shouldRenderJobPanel(string $status): bool
153 {
154 return $status === QueuedBackup::STATUS_RUNNING && $this->postValue('needPanel') === '1';
155 }
156
157 private function renderJobPanel(): string
158 {
159 ob_start();
160 require WPSTG_VIEWS_DIR . 'job/locked.php';
161
162 return (string)ob_get_clean();
163 }
164
165 /**
166 * @return void
167 */
168 public function ajaxCancelAction()
169 {
170 if (!$this->isAuthorized()) {
171 return;
172 }
173
174 $this->journey->cancelAction();
175
176 wp_send_json_success();
177 }
178
179 /**
180 * The one endpoint behind every explicit way out — "Skip for now", "Done",
181 * and leaving a running job behind — with the reason derived from where the
182 * user was standing rather than from what the browser claims.
183 */
184 public function ajaxFinish()
185 {
186 if (!$this->isAuthorized()) {
187 return;
188 }
189
190 $this->onboarding->finish();
191
192 wp_send_json_success();
193 }
194
195 /**
196 * Parks a backup to run once the staging site currently being created is done.
197 *
198 * Answers with the resulting status either way, so a repeated click or a
199 * replayed request renders the same acknowledgement instead of an error.
200 */
201 public function ajaxQueueBackup()
202 {
203 if (!$this->isAuthorized()) {
204 return;
205 }
206
207 $isFirstRun = $this->journey->isUnderWay();
208
209 if ($isFirstRun) {
210 $this->onboarding->recordBackupNextClicked();
211 }
212
213 if (!$this->journey->isFirstCapabilityCompleted() && $this->queuedBackup->queue($this->postValue('stagingJobId')) && $isFirstRun) {
214 $this->onboarding->selectAction(OnboardingJourney::CAPABILITY_BACKUP);
215 }
216
217 wp_send_json_success(['status' => $this->queuedBackup->getStatus()]);
218 }
219
220 private function isAuthorized(): bool
221 {
222 if ($this->auth->isAuthenticatedRequest('', 'manage_options')) {
223 return true;
224 }
225
226 wp_send_json_error(null, 401);
227
228 return false;
229 }
230
231 private function postValue(string $key): string
232 {
233 return isset($_POST[$key]) ? $this->sanitize->sanitizeString($_POST[$key]) : '';
234 }
235 }
236