PluginProbe ʕ •ᴥ•ʔ
WP STAGING – WordPress Backup, Restore, Migration & Clone / 4.9.2
WP STAGING – WordPress Backup, Restore, Migration & Clone v4.9.2
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 day ago I18n.php 1 day ago
Assets.php
758 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\Facades\Escape;
8 use WPStaging\Framework\Filesystem\PartIdentifier;
9 use WPStaging\Framework\Language\Language;
10 use WPStaging\Core\DTO\Settings;
11 use WPStaging\Core\WPStaging;
12 use WPStaging\Framework\Filesystem\Scanning\ScanConst;
13 use WPStaging\Framework\Security\AccessToken;
14 use WPStaging\Framework\Security\Nonce;
15 use WPStaging\Framework\Traits\ResourceTrait;
16 use WPStaging\Framework\SiteInfo;
17 use WPStaging\Framework\Analytics\AnalyticsConsent;
18 use WPStaging\Framework\Facades\Hooks;
19 use WPStaging\Framework\Notices\Notices;
20 use WPStaging\Framework\Notices\CliIntegrationNotice;
21 use WPStaging\Framework\Newsfeed\NewsfeedProvider;
22 use WPStaging\Framework\Rest\Rest;
23 use WPStaging\Backup\Storage\Providers;
24 use WPStaging\Framework\Settings\DarkMode;
25 use WPStaging\Staging\Service\StagingEngine;
26
27 class Assets
28 {
29 use ResourceTrait;
30
31 /**
32 * Default admin bar background color for staging site
33 * @var string
34 */
35 const DEFAULT_ADMIN_BAR_BG = "#ff8d00";
36
37 /** @var string */
38 const FILTER_BACKUP_STATUS_REQUEST_INTERVAL = 'wpstg.backup.interval.status_request';
39
40 /** @var string */
41 const FILTER_STAGING_SITE_TITLE = 'wpstg_staging_site_title';
42
43 const FILTER_TESTS_MAXIMUM_RETRIES = 'wpstg.tests.maximum_retries';
44
45 /** @var string */
46 const TRANSIENT_REST_URL = 'wpstg_rest_url';
47
48 private $accessToken;
49
50 protected $settings;
51
52 private $analyticsConsent;
53
54 /** @var I18n */
55 private $i18n;
56
57 /** @var Providers */
58 private $providers;
59
60 public function __construct(AccessToken $accessToken, Settings $settings, AnalyticsConsent $analyticsConsent, I18n $i18n, Providers $providers)
61 {
62 $this->accessToken = $accessToken;
63 $this->settings = $settings;
64 $this->analyticsConsent = $analyticsConsent;
65 $this->i18n = $i18n;
66 $this->providers = $providers;
67 }
68
69 /**
70 * Prepend the URL to the assets to the given file
71 *
72 * @param string $assetsFile optional
73 * @return string
74 */
75 public function getAssetsUrl($assetsFile = '')
76 {
77 return WPSTG_PLUGIN_URL . "assets/$assetsFile";
78 }
79
80 /**
81 * Get minified or non minified css file name based on debug mode
82 * @param string $cssFileNameWithoutExtension path without extension relative to wpstgPluginDir/assets/css/dist/
83 * @return string
84 */
85 public function getCssAssetsFileName(string $cssFileNameWithoutExtension): string
86 {
87 // If in debug mode, get non-minified css file name if it exists
88 $nonMinCssFile = $this->getAssetsPath("css/dist/$cssFileNameWithoutExtension.css");
89 if ($this->isDebugOrDevMode() && file_exists($nonMinCssFile)) {
90 return "css/dist/$cssFileNameWithoutExtension.css";
91 }
92
93 return "css/dist/$cssFileNameWithoutExtension.min.css";
94 }
95
96 /**
97 * Get minified or non minified js file name based on debug mode
98 * @param string $jsFileNameWithoutExtension path without extension relative to wpstgPluginDir/assets/js/dist/
99 * @return string
100 */
101 public function getJsAssetsFileName(string $jsFileNameWithoutExtension): string
102 {
103 // If in debug mode, get non-minified js file name if it exists
104 $nonMinJsFile = $this->getAssetsPath("js/dist/$jsFileNameWithoutExtension.js");
105 if ($this->isDebugOrDevMode() && file_exists($nonMinJsFile)) {
106 return "js/dist/$jsFileNameWithoutExtension.js";
107 }
108
109 return "js/dist/$jsFileNameWithoutExtension.min.js";
110 }
111
112 /**
113 * Get the version the given file. Use for caching
114 *
115 * @param string $assetsFile
116 * @param string $assetsVersion use WPStaging::getVersion() instead if not given
117 * @return string
118 */
119 public function getAssetsUrlWithVersion($assetsFile, $assetsVersion = '')
120 {
121 $url = $this->getAssetsUrl($assetsFile);
122 $ver = empty($assetsVersion) ? $this->getAssetsVersion($assetsFile, $assetsVersion) : $assetsVersion;
123 return $url . '?v=' . $ver;
124 }
125
126 /**
127 * Prepend the Path to the assets to the given file
128 *
129 * @param string $assetsFile optional
130 * @return string
131 */
132 public function getAssetsPath($assetsFile = '')
133 {
134 return WPSTG_PLUGIN_DIR . "assets/$assetsFile";
135 }
136
137 /**
138 * Get the version the given file. Use for caching
139 *
140 * @param string $assetsFile
141 * @param string $assetsVersion Optional, use WPStaging::getVersion() instead if not given
142 * @return string|int
143 */
144 public function getAssetsVersion($assetsFile, $assetsVersion = '')
145 {
146 $filename = $this->getAssetsPath($assetsFile);
147 $filemtime = file_exists($filename) ? @filemtime($filename) : false;
148
149 if ($filemtime !== false) {
150 return $filemtime;
151 } else {
152 return $assetsVersion !== '' ? $assetsVersion : WPStaging::getVersion();
153 }
154 }
155
156 /**
157 * @action admin_enqueue_scripts 100 1
158 * @action wp_enqueue_scripts 100 1
159 */
160 public function enqueueElements($hook)
161 {
162 $this->loadGlobalAssets($hook);
163
164 add_action(Notices::ACTION_INJECT_ANALYTICS_CONSENT_ASSETS, [$this, 'enqueueAnalyticsConsentAssets'], 10, 0);
165
166 // Load this css file on frontend and backend on all pages if current site is a staging site
167 if ((new SiteInfo())->isStagingSite()) {
168 wp_register_style('wpstg-admin-bar', false);
169 wp_enqueue_style('wpstg-admin-bar');
170 wp_add_inline_style('wpstg-admin-bar', $this->getStagingAdminBarColor());
171 }
172
173 // Load feedback form js file on page plugins.php in free version or in free dev version
174 if (!WPStaging::isPro() && $this->isPluginsPage()) {
175 $asset = $this->getJsAssetsFileName('wpstg-admin-plugins');
176 wp_enqueue_script(
177 "wpstg-admin-script",
178 $this->getAssetsUrl($asset),
179 ["jquery"],
180 $this->getAssetsVersion($asset),
181 $this->getScriptLoadingStrategy()
182 );
183
184 $asset = $this->getCssAssetsFileName('wpstg-admin-feedback');
185 wp_enqueue_style(
186 "wpstg-admin-feedback",
187 $this->getAssetsUrl($asset),
188 [],
189 $this->getAssetsVersion($asset)
190 );
191 }
192
193 // Load js file on admin pages for pro version
194 if (WPStaging::isPro() && is_admin()) {
195 $asset = $this->getJsAssetsFileName('pro/wpstg-admin-all-pages');
196 wp_enqueue_script(
197 "wpstg-admin-all-pages-script",
198 $this->getAssetsUrl($asset),
199 ["jquery"],
200 $this->getAssetsVersion($asset),
201 $this->getScriptLoadingStrategy()
202 );
203
204 $asset = $this->getCssAssetsFileName('wpstg-admin-all-pages');
205 wp_enqueue_style(
206 "wpstg-admin-all-pages-style",
207 $this->getAssetsUrl($asset),
208 [],
209 $this->getAssetsVersion($asset)
210 );
211 }
212
213 // Load below assets only on WP Staging admin pages
214 if ($this->isNotWPStagingAdminPage($hook)) {
215 return;
216 }
217
218 // Load wpstg js files
219 $asset = $this->getJsAssetsFileName('wpstg');
220 wp_enqueue_script(
221 "wpstg-common",
222 $this->getAssetsUrl($asset),
223 ["jquery"],
224 $this->getAssetsVersion($asset),
225 $this->getScriptLoadingStrategy()
226 );
227
228 // Load admin js files
229 $asset = $this->getJsAssetsFileName('wpstg-admin');
230 wp_enqueue_script(
231 "wpstg-admin-script",
232 $this->getAssetsUrl($asset),
233 ["wpstg-common", "wpstg-admin-notyf", "wpstg-admin-sweetalerts"],
234 $this->getAssetsVersion($asset),
235 $this->getScriptLoadingStrategy()
236 );
237
238 // Load SolidJS bundle if it exists
239 $solidAsset = $this->getJsAssetsFileName('wpstg-solid');
240 $solidAssetPath = $this->getAssetsPath($solidAsset);
241 if (file_exists($solidAssetPath)) {
242 wp_enqueue_script(
243 "wpstg-solid",
244 $this->getAssetsUrl($solidAsset),
245 ["wpstg-admin-script"],
246 $this->getAssetsVersion($solidAsset),
247 $this->getScriptLoadingStrategy()
248 );
249 }
250
251 // Load settings page js file
252 if (is_admin() && isset($_GET['page']) && $_GET['page'] === 'wpstg-settings') {
253 $asset = $this->getJsAssetsFileName('wpstg-admin-settings');
254 wp_enqueue_script(
255 'wpstg-admin-settings-script',
256 $this->getAssetsUrl($asset),
257 ['wpstg-common'],
258 $this->getAssetsVersion($asset),
259 $this->getScriptLoadingStrategy()
260 );
261 }
262
263 // Sweet Alert
264 $asset = $this->getJsAssetsFileName('wpstg-sweetalert2');
265 wp_enqueue_script(
266 'wpstg-admin-sweetalerts',
267 $this->getAssetsUrl($asset),
268 [],
269 $this->getAssetsVersion($asset),
270 $this->getScriptLoadingStrategy()
271 );
272
273 $asset = $this->getCssAssetsFileName('wpstg-sweetalert2');
274 wp_enqueue_style(
275 'wpstg-admin-sweetalerts',
276 $this->getAssetsUrl($asset),
277 [],
278 $this->getAssetsVersion($asset)
279 );
280
281 // Notyf Toast Notification
282 $asset = 'js/vendor/notyf.min.js';
283 wp_enqueue_script(
284 'wpstg-admin-notyf',
285 $this->getAssetsUrl($asset),
286 [],
287 $this->getAssetsVersion($asset),
288 $this->getScriptLoadingStrategy()
289 );
290
291 $asset = 'css/vendor/notyf.min.css';
292 wp_enqueue_style(
293 'wpstg-admin-notyf',
294 $this->getAssetsUrl($asset),
295 [],
296 $this->getAssetsVersion($asset)
297 );
298
299 // Internal hook to enqueue backup scripts, used by the backup addon
300 Hooks::doAction(BackupServiceProvider::ACTION_BACKUP_ENQUEUE_SCRIPTS);
301
302 // Load storage array to js for show/hide the badge-pill
303 wp_localize_script('wpstg-backup', 'wpstgAllStorages', $this->providers->getStorages(true));
304
305 // Load admin js pro files
306 if (WPStaging::isPro()) {
307 $asset = $this->getJsAssetsFileName('pro/wpstg-admin-pro');
308 wp_enqueue_script(
309 "wpstg-admin-pro-script",
310 $this->getAssetsUrl($asset),
311 ["jquery", "wpstg-common", "wpstg-admin-script", "wpstg-admin-notyf", "wpstg-admin-sweetalerts"],
312 $this->getAssetsVersion($asset),
313 $this->getScriptLoadingStrategy()
314 );
315 }
316
317 // Load admin css files
318 $asset = $this->getCssAssetsFileName('wpstg-admin');
319 wp_enqueue_style(
320 "wpstg-admin",
321 $this->getAssetsUrl($asset),
322 [],
323 $this->getAssetsVersion($asset)
324 );
325
326 $wpstgConfig = [
327 "delayReq" => 0,
328 // The interval in milliseconds between each request of backup status
329 'backupStatusInterval' => Hooks::applyFilters(self::FILTER_BACKUP_STATUS_REQUEST_INTERVAL, 8000),
330 "settings" => (object)[
331 "directorySeparator" => ScanConst::DIRECTORIES_SEPARATOR,
332 ],
333 "tblprefix" => WPStaging::getTablePrefix(),
334 "isMultisite" => is_multisite(),
335 AccessToken::REQUEST_KEY => (string)$this->accessToken->getToken() ?: (string)$this->accessToken->generateNewToken(),
336 'nonce' => wp_create_nonce(Nonce::WPSTG_NONCE),
337 'assetsUrl' => $this->getAssetsUrl(),
338 'ajaxUrl' => admin_url('admin-ajax.php'),
339 'restUrl' => $this->getRestUrl(),
340 'wpstgIcon' => $this->getAssetsUrl('img/wpstg-loader.gif'),
341 'maxUploadChunkSize' => $this->getMaxUploadChunkSize(),
342 'backupDBExtension' => PartIdentifier::DATABASE_PART_IDENTIFIER . '.' . DatabaseImporter::FILE_FORMAT,
343 'analyticsConsentAllow' => esc_url($this->analyticsConsent->getConsentLink(true)),
344 'analyticsConsentDeny' => esc_url($this->analyticsConsent->getConsentLink(false)),
345 'analyticsConsentLater' => esc_url($this->analyticsConsent->getRemindMeLaterConsentLink()),
346 'pluginVersion' => WPStaging::getVersion(),
347 'isPro' => WPStaging::isPro(),
348 'isDeveloperOrHigherLicense' => WPStaging::make(CliIntegrationNotice::class)->isDeveloperOrHigherLicense(),
349 'isExpiredDeveloperOrHigherLicense' => WPStaging::make(CliIntegrationNotice::class)->isExpiredDeveloperOrHigherLicense(),
350 'canExtractSingleFile' => WPStaging::isPro() && $this->isValidProLicense(),
351 'licensePlanName' => WPStaging::make(CliIntegrationNotice::class)->getLicensePlanName(),
352 'licenseUpgradeUrl' => $this->getLicenseUpgradeUrl(),
353 'licenseRenewalUrl' => $this->getLicenseRenewalUrl(),
354 'pricingUrl' => Language::getUpgradeUrl('plugin_upsell'),
355 'checkoutFallbackUrl' => Language::localizeCheckoutUrl('https://wp-staging.com/checkout/?nocache=true&download_id=11'),
356 'newsfeedData' => $this->getNewsfeedDataForJs(),
357 'isNewUser' => $this->isNewUser(),
358 'maxFailedRetries' => apply_filters(self::FILTER_TESTS_MAXIMUM_RETRIES, 10),
359 'i18n' => $this->i18n->getTranslations(),
360 'isCloneable' => (new SiteInfo())->isCloneable(),
361 'isTestMode' => defined('WPSTG_TEST') && WPSTG_TEST,
362 'defaultColorMode' => get_option(DarkMode::OPTION_DEFAULT_COLOR_MODE, ''),
363 'siteUrl' => site_url(),
364 'stagingEnginePreference' => WPStaging::make(StagingEngine::class)->getEngine(),
365 ];
366
367 // We need some wpstgConfig vars in the wpstg.js file (loaded with wpstg-common scripts) as well
368 wp_localize_script("wpstg-common", "wpstg", $wpstgConfig);
369 // Add test mode body class if WPSTG_TEST is defined
370 if (defined('WPSTG_TEST') && WPSTG_TEST) {
371 add_filter('admin_body_class', function ($classes) {
372 return $classes . ' wpstg-test-mode';
373 });
374 }
375 }
376
377 public function enqueueAnalyticsConsentAssets()
378 {
379 $asset = $this->getJsAssetsFileName('analytics-consent-modal');
380 wp_enqueue_script(
381 "wpstg-show-analytics-modal",
382 $this->getAssetsUrl($asset),
383 [],
384 $this->getAssetsVersion($asset),
385 $this->getScriptLoadingStrategy()
386 );
387
388 $asset = $this->getCssAssetsFileName('analytics-consent-modal');
389 wp_enqueue_style(
390 'wpstg-plugin-activation',
391 $this->getAssetsUrl($asset),
392 [],
393 $this->getAssetsVersion($asset)
394 );
395 }
396
397 /**
398 * Load js vars globally but NOT on WP Staging admin pages or frontend
399 *
400 * @param string $pageSlug
401 * @return void
402 */
403 private function loadGlobalAssets($pageSlug)
404 {
405 if (!$this->isNotWPStagingAdminPage($pageSlug) || !is_admin()) {
406 return;
407 }
408
409 $asset = $this->getJsAssetsFileName('wpstg-blank-loader');
410 wp_enqueue_script('wpstg-global', $this->getAssetsUrl($asset), [], false, $this->getScriptLoadingStrategy());
411
412 $vars = [
413 'nonce' => wp_create_nonce(Nonce::WPSTG_NONCE),
414 ];
415
416 wp_localize_script("wpstg-global", "wpstg", $vars);
417 }
418
419 /**
420 * @return int The max upload size for a file.
421 */
422 protected function getMaxUploadChunkSize()
423 {
424 $lowerLimit = 64 * KB_IN_BYTES;
425 $upperLimit = 16 * MB_IN_BYTES;
426
427 $maxPostSize = wp_convert_hr_to_bytes(ini_get('post_max_size'));
428 $uploadMaxFileSize = wp_convert_hr_to_bytes(ini_get('upload_max_filesize'));
429
430 // The real limit, read from the PHP context.
431 $limit = min($maxPostSize, $uploadMaxFileSize) * 0.90;
432
433 // Do not allow going over upper limit.
434 $limit = min($limit, $upperLimit);
435
436 // Do not allow going under lower limit.
437 $limit = max($lowerLimit, $limit);
438
439 return (int)$limit;
440 }
441
442 /**
443 * @return array|null
444 */
445 private function getNewsfeedDataForJs()
446 {
447 try {
448 /** @var NewsfeedProvider $provider */
449 $provider = WPStaging::make(NewsfeedProvider::class);
450 return $provider->getNewsfeedData();
451 } catch (\Exception $e) {
452 return null;
453 }
454 }
455
456 /**
457 * Whether this is a brand-new install that has never been upgraded from a
458 * previous version. The "what's new" modal is meant to inform existing users
459 * what an update brings, so it must not greet new users on their first visit.
460 *
461 * The "upgraded from" option is empty on a fresh install and holds the prior
462 * version once a real upgrade has happened, which cleanly tells the two apart.
463 *
464 * @return bool
465 */
466 private function isNewUser(): bool
467 {
468 $upgradedFromOption = WPStaging::isPro() ? 'wpstgpro_version_upgraded_from' : 'wpstg_version_upgraded_from';
469
470 return empty(get_option($upgradedFromOption, ''));
471 }
472
473 /**
474 * @return bool
475 */
476 private function isValidProLicense(): bool
477 {
478 if (!class_exists('\WPStaging\Pro\License\Licensing')) {
479 return false;
480 }
481
482 try {
483 return WPStaging::make(\WPStaging\Pro\License\Licensing::class)->isRegisteredLicense();
484 } catch (\Exception $e) {
485 return false;
486 }
487 }
488
489 /**
490 * @return string
491 */
492 private function getLicenseUpgradeUrl(): string
493 {
494 if (!WPStaging::isPro() || !class_exists('\WPStaging\Pro\License\Licensing')) {
495 return '';
496 }
497
498 try {
499 /** @var \WPStaging\Pro\License\Licensing $licensing */
500 $licensing = WPStaging::make(\WPStaging\Pro\License\Licensing::class);
501 return $licensing->getUpgradeToDevUrl();
502 } catch (\Exception $e) {
503 return '';
504 }
505 }
506
507 /**
508 * @return string
509 */
510 private function getLicenseRenewalUrl(): string
511 {
512 if (!WPStaging::isPro() || !class_exists('\WPStaging\Pro\License\Licensing')) {
513 return '';
514 }
515
516 try {
517 $isExpired = WPStaging::make(CliIntegrationNotice::class)->isExpiredDeveloperOrHigherLicense();
518 if (!$isExpired) {
519 return '';
520 }
521
522 $licenseKey = trim(get_option(\WPStaging\Pro\License\Licensing::WPSTG_LICENSE_KEY, ''));
523 return Language::localizeCheckoutUrl('https://wp-staging.com/checkout/?nocache=true&edd_license_key=' . urlencode($licenseKey) . '&download_id=11');
524 } catch (\Exception $e) {
525 return '';
526 }
527 }
528
529 /**
530 * Get the script loading args for wp_enqueue_script's 5th parameter.
531 * On WP 6.5+: uses defer strategy (loads in head, downloads in parallel, executes after parsing).
532 * On older WP: loads in footer as fallback to avoid render-blocking.
533 *
534 * @return array|bool
535 */
536 public function getScriptLoadingStrategy()
537 {
538 if (function_exists('wp_register_script_module')) {
539 return ['strategy' => 'defer', 'in_footer' => false];
540 }
541
542 return true;
543 }
544
545 /**
546 * Check given slug is not WP Staging admin page
547 *
548 * @param string $slug slug of the current page
549 *
550 * @return bool
551 */
552 private function isNotWPStagingAdminPage($slug)
553 {
554 if (WPStaging::isPro() || WPStaging::isDevBasic()) {
555 $availableSlugs = [
556 "toplevel_page_wpstg_clone",
557 "toplevel_page_wpstg_backup",
558 "wp-staging-pro_page_wpstg_clone",
559 "wp-staging-pro_page_wpstg_backup",
560 "wp-staging-pro_page_wpstg-settings",
561 "wp-staging-pro_page_wpstg-tools",
562 "wp-staging-pro_page_wpstg-license",
563 "wp-staging-pro_page_wpstg-restorer",
564 // DevBasic mode uses the basic dist plugin (wp-staging/) with WPSTG_DEV_BASIC constant,
565 // so WordPress generates wp-staging_page_* slugs instead of wp-staging-pro_page_*
566 "wp-staging_page_wpstg_clone",
567 "wp-staging_page_wpstg_backup",
568 "wp-staging_page_wpstg-settings",
569 "wp-staging_page_wpstg-tools",
570 ];
571 } else {
572 $availableSlugs = [
573 "toplevel_page_wpstg_clone",
574 "toplevel_page_wpstg_backup",
575 "wp-staging_page_wpstg_clone",
576 "wp-staging_page_wpstg_backup",
577 "wp-staging_page_wpstg-settings",
578 "wp-staging_page_wpstg-tools",
579 "wp-staging_page_wpstg-welcome",
580 ];
581 }
582
583 return !in_array($slug, $availableSlugs);
584 }
585
586 /**
587 * Remove heartbeat api and user login check
588 *
589 * @action admin_enqueue_scripts 100 1
590 * @see AssetServiceProvider.php
591 *
592 * @param string $hook
593 */
594 public function removeWPCoreJs($hook)
595 {
596 if ($this->isNotWPStagingAdminPage($hook)) {
597 return;
598 }
599
600 // Disable user login status check
601 // Todo: Can we remove this now that we have AccessToken?
602 remove_action('admin_enqueue_scripts', 'wp_auth_check_load');
603
604 // Disable heartbeat check for cloning and pushing
605 wp_deregister_script('heartbeat');
606 }
607
608 /**
609 * Check if current page is plugins.php
610 * @global array $pagenow
611 * @return bool
612 */
613 private function isPluginsPage()
614 {
615 global $pagenow;
616
617 return ($pagenow === 'plugins.php');
618 }
619
620 /**
621 * @return string
622 */
623 public function getStagingAdminBarColor()
624 {
625 $barColor = $this->settings->getAdminBarColor();
626 if (!preg_match("/#([a-f0-9]{3}){1,2}\b/i", $barColor)) {
627 $barColor = self::DEFAULT_ADMIN_BAR_BG;
628 }
629
630 return "#wpadminbar { background-color: {$barColor} !important; }";
631 }
632
633 /**
634 * Check whether app is in debug mode or in dev mode
635 *
636 * @return bool
637 */
638 private function isDebugOrDevMode()
639 {
640 return ($this->settings->isDebugMode() || (defined('WPSTG_IS_DEV') && WPSTG_IS_DEV === true) || (defined('WPSTG_DEBUG') && WPSTG_DEBUG === true));
641 }
642
643 /**
644 * Change admin_bar site_name
645 *
646 * @return void
647 * @global object $wp_admin_bar
648 */
649 public function changeSiteName()
650 {
651 if (!(new SiteInfo())->isStagingSite()) {
652 return;
653 }
654
655 global $wp_admin_bar;
656 $blogName = get_bloginfo('name');
657 if (empty($blogName)) {
658 $siteUrl = get_site_url();
659 $parsedUrl = parse_url($siteUrl);
660 $blogName = $parsedUrl['host'];
661 }
662
663 $siteTitle = Hooks::applyFilters(self::FILTER_STAGING_SITE_TITLE, 'STAGING');
664 $title = (strlen($blogName) > 20) ? substr($blogName, 0, 20) . '...' : $blogName;
665 $wp_admin_bar->add_menu(
666 [
667 'id' => 'site-name',
668 'title' => $siteTitle . ' - ' . $title,
669 'href' => is_admin() ? home_url('/') : admin_url(),
670 ]
671 );
672 }
673
674 /**
675 * @param string $hook
676 * @return void
677 */
678 public function dequeueNonWpstgElements($hook)
679 {
680 if ($this->isNotWPStagingAdminPage($hook)) {
681 return;
682 }
683
684 $stylesToRemove = ['wp-reset-sweetalert2'];
685 $scriptsToRemove = [
686 'wp-reset-sweetalert2',
687 'wp-reset',
688 ];
689
690 foreach ($stylesToRemove as $style) {
691 wp_dequeue_style($style);
692 }
693
694 foreach ($scriptsToRemove as $script) {
695 wp_dequeue_script($script);
696 }
697 }
698
699 /**
700 * @param string $iconName
701 * @param string $class
702 * @return void
703 */
704 public function renderSvg(string $iconName, string $class = '')
705 {
706 $fullPath = WPSTG_PLUGIN_DIR . '/assets/svg/' . $iconName . '.svg';
707 if (!file_exists($fullPath)) {
708 return;
709 }
710
711 $svgCode = file_get_contents($fullPath);
712 $svgCode = preg_replace('/<svg(.*?)>/', '<svg$1 class="' . $class . '">', $svgCode);
713 echo Escape::escapeHtml($svgCode);
714 }
715
716
717 private function getRestUrl(): string
718 {
719 $restUrl = get_transient(self::TRANSIENT_REST_URL);
720 if ($restUrl) {
721 return $restUrl;
722 }
723
724 $restUrl = get_rest_url(null, Rest::WPSTG_ROUTE_NAMESPACE_V1);
725 if (!$this->isWorkingTestUrl($restUrl)) {
726 $restUrl = site_url('/?rest_route=/' . Rest::WPSTG_ROUTE_NAMESPACE_V1);
727 }
728
729 set_transient(self::TRANSIENT_REST_URL, $restUrl, 24 * HOUR_IN_SECONDS);
730
731 return $restUrl;
732 }
733
734 private function isWorkingTestUrl($url)
735 {
736 $url .= '/ping&accessToken=' . $this->accessToken->getToken();
737 $response = wp_remote_request($url, [
738 'method' => 'GET',
739 'timeout' => 5,
740 'sslverify' => false,
741 'headers' => [
742 'Accept' => 'application/json',
743 ],
744 ]);
745
746 if (is_wp_error($response)) {
747 return false;
748 }
749
750 $code = wp_remote_retrieve_response_code($response);
751 if ($code !== 200) {
752 return false;
753 }
754
755 return true;
756 }
757 }
758