PluginProbe ʕ •ᴥ•ʔ
WP STAGING – WordPress Backups, Restore, Migration & Clone / 4.0.0
WP STAGING – WordPress Backups, Restore, Migration & Clone v4.0.0
4.11.2 4.11.1 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 / Framework / Assets / Assets.php
wp-staging / Framework / Assets Last commit date
Assets.php 1 year ago I18n.php 1 year ago
Assets.php
493 lines
1 <?php
2
3 namespace WPStaging\Framework\Assets;
4
5 use WPStaging\Backup\BackupServiceProvider;
6 use WPStaging\Backup\Service\Database\DatabaseImporter;
7 use WPStaging\Framework\Job\AbstractJob;
8 use WPStaging\Framework\Filesystem\PartIdentifier;
9 use WPStaging\Core\DTO\Settings;
10 use WPStaging\Core\WPStaging;
11 use WPStaging\Framework\Filesystem\Scanning\ScanConst;
12 use WPStaging\Framework\Security\AccessToken;
13 use WPStaging\Framework\Security\Nonce;
14 use WPStaging\Framework\Traits\ResourceTrait;
15 use WPStaging\Framework\SiteInfo;
16 use WPStaging\Framework\Analytics\AnalyticsConsent;
17 use WPStaging\Framework\Facades\Hooks;
18 use WPStaging\Framework\Notices\Notices;
19
20 class Assets
21 {
22 use ResourceTrait;
23
24 /**
25 * Default admin bar background color for staging site
26 * @var string
27 */
28 const DEFAULT_ADMIN_BAR_BG = "#ff8d00";
29
30 /** @var string */
31 const FILTER_BACKUP_STATUS_REQUEST_INTERVAL = 'wpstg.backup.interval.status_request';
32
33 private $accessToken;
34
35 private $settings;
36
37 private $analyticsConsent;
38
39 /** @var I18n */
40 private $i18n;
41
42 public function __construct(AccessToken $accessToken, Settings $settings, AnalyticsConsent $analyticsConsent, I18n $i18n)
43 {
44 $this->accessToken = $accessToken;
45 $this->settings = $settings;
46 $this->analyticsConsent = $analyticsConsent;
47 $this->i18n = $i18n;
48 }
49
50 /**
51 * Prepend the URL to the assets to the given file
52 *
53 * @param string $assetsFile optional
54 * @return string
55 */
56 public function getAssetsUrl($assetsFile = '')
57 {
58 return WPSTG_PLUGIN_URL . "assets/$assetsFile";
59 }
60
61 /**
62 * Get minified or non minified css file name based on debug mode
63 * @param string $cssFileNameWithoutExtension path without extension relative to wpstgPluginDir/assets/css/dist/
64 * @return string
65 */
66 public function getCssAssetsFileName(string $cssFileNameWithoutExtension): string
67 {
68 // If in debug mode, get non-minified css file name if it exists
69 $nonMinCssFile = $this->getAssetsPath("css/dist/$cssFileNameWithoutExtension.css");
70 if ($this->isDebugOrDevMode() && file_exists($nonMinCssFile)) {
71 return "css/dist/$cssFileNameWithoutExtension.css";
72 }
73
74 return "css/dist/$cssFileNameWithoutExtension.min.css";
75 }
76
77 /**
78 * Get minified or non minified js file name based on debug mode
79 * @param string $jsFileNameWithoutExtension path without extension relative to wpstgPluginDir/assets/js/dist/
80 * @return string
81 */
82 public function getJsAssetsFileName(string $jsFileNameWithoutExtension): string
83 {
84 // If in debug mode, get non-minified js file name if it exists
85 $nonMinJsFile = $this->getAssetsPath("js/dist/$jsFileNameWithoutExtension.js");
86 if ($this->isDebugOrDevMode() && file_exists($nonMinJsFile)) {
87 return "js/dist/$jsFileNameWithoutExtension.js";
88 }
89
90 return "js/dist/$jsFileNameWithoutExtension.min.js";
91 }
92
93 /**
94 * Get the version the given file. Use for caching
95 *
96 * @param string $assetsFile
97 * @param string $assetsVersion use WPStaging::getVersion() instead if not given
98 * @return string
99 */
100 public function getAssetsUrlWithVersion($assetsFile, $assetsVersion = '')
101 {
102 $url = $this->getAssetsUrl($assetsFile);
103 $ver = empty($assetsVersion) ? $this->getAssetsVersion($assetsFile, $assetsVersion) : $assetsVersion;
104 return $url . '?v=' . $ver;
105 }
106
107 /**
108 * Prepend the Path to the assets to the given file
109 *
110 * @param string $assetsFile optional
111 * @return string
112 */
113 public function getAssetsPath($assetsFile = '')
114 {
115 return WPSTG_PLUGIN_DIR . "assets/$assetsFile";
116 }
117
118 /**
119 * Get the version the given file. Use for caching
120 *
121 * @param string $assetsFile
122 * @param string $assetsVersion Optional, use WPStaging::getVersion() instead if not given
123 * @return string|int
124 */
125 public function getAssetsVersion($assetsFile, $assetsVersion = '')
126 {
127 $filename = $this->getAssetsPath($assetsFile);
128 $filemtime = file_exists($filename) ? @filemtime($filename) : false;
129
130 if ($filemtime !== false) {
131 return $filemtime;
132 } else {
133 return $assetsVersion !== '' ? $assetsVersion : WPStaging::getVersion();
134 }
135 }
136
137 /**
138 * @action admin_enqueue_scripts 100 1
139 * @action wp_enqueue_scripts 100 1
140 */
141 public function enqueueElements($hook)
142 {
143 $this->loadGlobalAssets($hook);
144
145 add_action(Notices::INJECT_ANALYTICS_CONSENT_ASSETS_ACTION, [$this, 'enqueueAnalyticsConsentAssets'], 10, 0);
146
147 // Load this css file on frontend and backend on all pages if current site is a staging site
148 if ((new SiteInfo())->isStagingSite()) {
149 wp_register_style('wpstg-admin-bar', false);
150 wp_enqueue_style('wpstg-admin-bar');
151 wp_add_inline_style('wpstg-admin-bar', $this->getStagingAdminBarColor());
152 }
153
154 // Load feedback form js file on page plugins.php in free version or in free dev version
155 if (!WPStaging::isPro() && $this->isPluginsPage()) {
156 $asset = $this->getJsAssetsFileName('wpstg-admin-plugins');
157 wp_enqueue_script(
158 "wpstg-admin-script",
159 $this->getAssetsUrl($asset),
160 ["jquery"],
161 $this->getAssetsVersion($asset),
162 false
163 );
164
165 $asset = $this->getCssAssetsFileName('wpstg-admin-feedback');
166 wp_enqueue_style(
167 "wpstg-admin-feedback",
168 $this->getAssetsUrl($asset),
169 [],
170 $this->getAssetsVersion($asset)
171 );
172 }
173
174 // Load js file on admin pages for pro version
175 if (WPStaging::isPro() && is_admin()) {
176 $asset = $this->getJsAssetsFileName('pro/wpstg-admin-all-pages');
177 wp_enqueue_script(
178 "wpstg-admin-all-pages-script",
179 $this->getAssetsUrl($asset),
180 ["jquery"],
181 $this->getAssetsVersion($asset),
182 false
183 );
184
185 $asset = $this->getCssAssetsFileName('wpstg-admin-all-pages');
186 wp_enqueue_style(
187 "wpstg-admin-all-pages-style",
188 $this->getAssetsUrl($asset),
189 [],
190 $this->getAssetsVersion($asset)
191 );
192 }
193
194 // Load below assets only on WP Staging admin pages
195 if ($this->isNotWPStagingAdminPage($hook)) {
196 return;
197 }
198
199 // Load wpstg js files
200 $asset = $this->getJsAssetsFileName('wpstg');
201 wp_enqueue_script(
202 "wpstg-common",
203 $this->getAssetsUrl($asset),
204 ["jquery"],
205 $this->getAssetsVersion($asset),
206 false
207 );
208
209 // Load admin js files
210 $asset = $this->getJsAssetsFileName('wpstg-admin');
211 wp_enqueue_script(
212 "wpstg-admin-script",
213 $this->getAssetsUrl($asset),
214 ["wpstg-common", "wpstg-admin-notyf", "wpstg-admin-sweetalerts"],
215 $this->getAssetsVersion($asset),
216 false
217 );
218
219 // Sweet Alert
220 $asset = $this->getJsAssetsFileName('wpstg-sweetalert2');
221 wp_enqueue_script(
222 'wpstg-admin-sweetalerts',
223 $this->getAssetsUrl($asset),
224 [],
225 $this->getAssetsVersion($asset),
226 true
227 );
228
229 $asset = $this->getCssAssetsFileName('wpstg-sweetalert2');
230 wp_enqueue_style(
231 'wpstg-admin-sweetalerts',
232 $this->getAssetsUrl($asset),
233 [],
234 $this->getAssetsVersion($asset)
235 );
236
237 // Notyf Toast Notification
238 $asset = 'js/vendor/notyf.min.js';
239 wp_enqueue_script(
240 'wpstg-admin-notyf',
241 $this->getAssetsUrl($asset),
242 [],
243 $this->getAssetsVersion($asset),
244 true
245 );
246
247 $asset = 'css/vendor/notyf.min.css';
248 wp_enqueue_style(
249 'wpstg-admin-notyf',
250 $this->getAssetsUrl($asset),
251 [],
252 $this->getAssetsVersion($asset)
253 );
254
255 // Internal hook to enqueue backup scripts, used by the backup addon
256 Hooks::doAction(BackupServiceProvider::BACKUP_SCRIPTS_ENQUEUE_ACTION);
257
258 // Load admin js pro files
259 if (WPStaging::isPro()) {
260 $asset = $this->getJsAssetsFileName('pro/wpstg-admin-pro');
261 wp_enqueue_script(
262 "wpstg-admin-pro-script",
263 $this->getAssetsUrl($asset),
264 ["jquery", "wpstg-admin-notyf", "wpstg-admin-sweetalerts"],
265 $this->getAssetsVersion($asset),
266 false
267 );
268 }
269
270 // Load admin css files
271 $asset = $this->getCssAssetsFileName('wpstg-admin');
272 wp_enqueue_style(
273 "wpstg-admin",
274 $this->getAssetsUrl($asset),
275 [],
276 $this->getAssetsVersion($asset)
277 );
278
279 $wpstgConfig = [
280 "delayReq" => 0,
281 // The interval in milliseconds between each request of backup status
282 'backupStatusInterval' => Hooks::applyFilters(self::FILTER_BACKUP_STATUS_REQUEST_INTERVAL, 8000),
283 "settings" => (object)[
284 "directorySeparator" => ScanConst::DIRECTORIES_SEPARATOR
285 ],
286 "tblprefix" => WPStaging::getTablePrefix(),
287 "isMultisite" => is_multisite(),
288 AccessToken::REQUEST_KEY => (string)$this->accessToken->getToken() ?: (string)$this->accessToken->generateNewToken(),
289 'nonce' => wp_create_nonce(Nonce::WPSTG_NONCE),
290 'assetsUrl' => $this->getAssetsUrl(),
291 'ajaxUrl' => admin_url('admin-ajax.php'),
292 'wpstgIcon' => $this->getAssetsUrl('img/wpstg-loader.gif'),
293 'maxUploadChunkSize' => $this->getMaxUploadChunkSize(),
294 'backupDBExtension' => PartIdentifier::DATABASE_PART_IDENTIFIER . '.' . DatabaseImporter::FILE_FORMAT,
295 'analyticsConsentAllow' => esc_url($this->analyticsConsent->getConsentLink(true)),
296 'analyticsConsentDeny' => esc_url($this->analyticsConsent->getConsentLink(false)),
297 'isPro' => WPStaging::isPro(),
298 'maxFailedRetries' => Hooks::applyFilters(AbstractJob::TEST_FILTER_MAXIMUM_RETRIES, 10),
299 'i18n' => $this->i18n->getTranslations(),
300 ];
301
302 // We need some wpstgConfig vars in the wpstg.js file (loaded with wpstg-common scripts) as well
303 wp_localize_script("wpstg-common", "wpstg", $wpstgConfig);
304 }
305
306 public function enqueueAnalyticsConsentAssets()
307 {
308 $asset = $this->getJsAssetsFileName('analytics-consent-modal');
309 wp_enqueue_script(
310 "wpstg-show-analytics-modal",
311 $this->getAssetsUrl($asset),
312 [],
313 $this->getAssetsVersion($asset)
314 );
315
316 $asset = $this->getCssAssetsFileName('analytics-consent-modal');
317 wp_enqueue_style(
318 'wpstg-plugin-activation',
319 $this->getAssetsUrl($asset),
320 [],
321 $this->getAssetsVersion($asset)
322 );
323 }
324
325 /**
326 * Load js vars globally but NOT on WP Staging admin pages or frontend
327 *
328 * @param string $pageSlug
329 * @return void
330 */
331 private function loadGlobalAssets($pageSlug)
332 {
333 if (!$this->isNotWPStagingAdminPage($pageSlug) || !is_admin()) {
334 return;
335 }
336
337 $asset = $this->getJsAssetsFileName('wpstg-blank-loader');
338 wp_enqueue_script('wpstg-global', $this->getAssetsUrl($asset), [], [], false);
339
340 $vars = [
341 'nonce' => wp_create_nonce(Nonce::WPSTG_NONCE),
342 ];
343
344 wp_localize_script("wpstg-global", "wpstg", $vars);
345 }
346
347 /**
348 * @return int The max upload size for a file.
349 */
350 protected function getMaxUploadChunkSize()
351 {
352 $lowerLimit = 64 * KB_IN_BYTES;
353 $upperLimit = 16 * MB_IN_BYTES;
354
355 $maxPostSize = wp_convert_hr_to_bytes(ini_get('post_max_size'));
356 $uploadMaxFileSize = wp_convert_hr_to_bytes(ini_get('upload_max_filesize'));
357
358 // The real limit, read from the PHP context.
359 $limit = min($maxPostSize, $uploadMaxFileSize) * 0.90;
360
361 // Do not allow going over upper limit.
362 $limit = min($limit, $upperLimit);
363
364 // Do not allow going under lower limit.
365 $limit = max($lowerLimit, $limit);
366
367 return (int)$limit;
368 }
369
370 /**
371 * Check given slug is not WP Staging admin page
372 *
373 * @param string $slug slug of the current page
374 *
375 * @return bool
376 */
377 private function isNotWPStagingAdminPage($slug)
378 {
379 if (WPStaging::isPro() || WPStaging::isDevBasic()) {
380 $availableSlugs = [
381 "toplevel_page_wpstg_clone",
382 "toplevel_page_wpstg_backup",
383 "wp-staging-pro_page_wpstg_clone",
384 "wp-staging-pro_page_wpstg_backup",
385 "wp-staging-pro_page_wpstg-settings",
386 "wp-staging-pro_page_wpstg-tools",
387 "wp-staging-pro_page_wpstg-license",
388 "wp-staging-pro_page_wpstg-restorer",
389 ];
390 } else {
391 $availableSlugs = [
392 "toplevel_page_wpstg_clone",
393 "toplevel_page_wpstg_backup",
394 "wp-staging_page_wpstg_clone",
395 "wp-staging_page_wpstg_backup",
396 "wp-staging_page_wpstg-settings",
397 "wp-staging_page_wpstg-tools",
398 "wp-staging_page_wpstg-welcome",
399 ];
400 }
401
402 return !in_array($slug, $availableSlugs);
403 }
404
405 /**
406 * Remove heartbeat api and user login check
407 *
408 * @action admin_enqueue_scripts 100 1
409 * @see AssetServiceProvider.php
410 *
411 * @param bool $hook
412 */
413 public function removeWPCoreJs($hook)
414 {
415 if ($this->isNotWPStagingAdminPage($hook)) {
416 return;
417 }
418
419 // Disable user login status check
420 // Todo: Can we remove this now that we have AccessToken?
421 remove_action('admin_enqueue_scripts', 'wp_auth_check_load');
422
423 // Disable heartbeat check for cloning and pushing
424 wp_deregister_script('heartbeat');
425 }
426
427 /**
428 * Check if current page is plugins.php
429 * @global array $pagenow
430 * @return bool
431 */
432 private function isPluginsPage()
433 {
434 global $pagenow;
435
436 return ($pagenow === 'plugins.php');
437 }
438
439 /**
440 * @return string
441 */
442 public function getStagingAdminBarColor()
443 {
444 $barColor = $this->settings->getAdminBarColor();
445 if (!preg_match("/#([a-f0-9]{3}){1,2}\b/i", $barColor)) {
446 $barColor = self::DEFAULT_ADMIN_BAR_BG;
447 }
448
449 return "#wpadminbar { background-color: {$barColor} !important; }";
450 }
451
452 /**
453 * Check whether app is in debug mode or in dev mode
454 *
455 * @return bool
456 */
457 private function isDebugOrDevMode()
458 {
459 return ($this->settings->isDebugMode() || (defined('WPSTG_IS_DEV') && WPSTG_IS_DEV === true) || (defined('WPSTG_DEBUG') && WPSTG_DEBUG === true));
460 }
461
462 /**
463 * Change admin_bar site_name
464 *
465 * @return void
466 * @global object $wp_admin_bar
467 */
468 public function changeSiteName()
469 {
470 if (!(new SiteInfo())->isStagingSite()) {
471 return;
472 }
473
474 global $wp_admin_bar;
475 $blogName = get_bloginfo('name');
476 if (empty($blogName)) {
477 $siteUrl = get_site_url();
478 $parsedUrl = parse_url($siteUrl);
479 $blogName = $parsedUrl['host'];
480 }
481
482 $siteTitle = apply_filters('wpstg_staging_site_title', 'STAGING');
483 $title = (strlen($blogName) > 20) ? substr($blogName, 0, 20) . '...' : $blogName;
484 $wp_admin_bar->add_menu(
485 [
486 'id' => 'site-name',
487 'title' => $siteTitle . ' - ' . $title,
488 'href' => is_admin() ? home_url('/') : admin_url(),
489 ]
490 );
491 }
492 }
493