PluginProbe ʕ •ᴥ•ʔ
WP STAGING – WordPress Backups, Restore, Migration & Clone / 4.9.5
WP STAGING – WordPress Backups, Restore, Migration & Clone v4.9.5
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 2 days ago I18n.php 4 weeks ago
Assets.php
759 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 'proFeaturesUrl' => Language::addClientAttribution(Language::localizeUrl('https://wp-staging.com/pro-features/?utm_source=wp-admin&utm_medium=plugin&utm_campaign=pro_features')),
356 'checkoutFallbackUrl' => Language::localizeCheckoutUrl('https://wp-staging.com/checkout/?nocache=true&download_id=11'),
357 'newsfeedData' => $this->getNewsfeedDataForJs(),
358 'isNewUser' => $this->isNewUser(),
359 'maxFailedRetries' => apply_filters(self::FILTER_TESTS_MAXIMUM_RETRIES, 10),
360 'i18n' => $this->i18n->getTranslations(),
361 'isCloneable' => (new SiteInfo())->isCloneable(),
362 'isTestMode' => defined('WPSTG_TEST') && WPSTG_TEST,
363 'defaultColorMode' => get_option(DarkMode::OPTION_DEFAULT_COLOR_MODE, ''),
364 'siteUrl' => site_url(),
365 'stagingEnginePreference' => WPStaging::make(StagingEngine::class)->getEngine(),
366 ];
367
368 // We need some wpstgConfig vars in the wpstg.js file (loaded with wpstg-common scripts) as well
369 wp_localize_script("wpstg-common", "wpstg", $wpstgConfig);
370 // Add test mode body class if WPSTG_TEST is defined
371 if (defined('WPSTG_TEST') && WPSTG_TEST) {
372 add_filter('admin_body_class', function ($classes) {
373 return $classes . ' wpstg-test-mode';
374 });
375 }
376 }
377
378 public function enqueueAnalyticsConsentAssets()
379 {
380 $asset = $this->getJsAssetsFileName('analytics-consent-modal');
381 wp_enqueue_script(
382 "wpstg-show-analytics-modal",
383 $this->getAssetsUrl($asset),
384 [],
385 $this->getAssetsVersion($asset),
386 $this->getScriptLoadingStrategy()
387 );
388
389 $asset = $this->getCssAssetsFileName('analytics-consent-modal');
390 wp_enqueue_style(
391 'wpstg-plugin-activation',
392 $this->getAssetsUrl($asset),
393 [],
394 $this->getAssetsVersion($asset)
395 );
396 }
397
398 /**
399 * Load js vars globally but NOT on WP Staging admin pages or frontend
400 *
401 * @param string $pageSlug
402 * @return void
403 */
404 private function loadGlobalAssets($pageSlug)
405 {
406 if (!$this->isNotWPStagingAdminPage($pageSlug) || !is_admin()) {
407 return;
408 }
409
410 $asset = $this->getJsAssetsFileName('wpstg-blank-loader');
411 wp_enqueue_script('wpstg-global', $this->getAssetsUrl($asset), [], false, $this->getScriptLoadingStrategy());
412
413 $vars = [
414 'nonce' => wp_create_nonce(Nonce::WPSTG_NONCE),
415 ];
416
417 wp_localize_script("wpstg-global", "wpstg", $vars);
418 }
419
420 /**
421 * @return int The max upload size for a file.
422 */
423 protected function getMaxUploadChunkSize()
424 {
425 $lowerLimit = 64 * KB_IN_BYTES;
426 $upperLimit = 16 * MB_IN_BYTES;
427
428 $maxPostSize = wp_convert_hr_to_bytes(ini_get('post_max_size'));
429 $uploadMaxFileSize = wp_convert_hr_to_bytes(ini_get('upload_max_filesize'));
430
431 // The real limit, read from the PHP context.
432 $limit = min($maxPostSize, $uploadMaxFileSize) * 0.90;
433
434 // Do not allow going over upper limit.
435 $limit = min($limit, $upperLimit);
436
437 // Do not allow going under lower limit.
438 $limit = max($lowerLimit, $limit);
439
440 return (int)$limit;
441 }
442
443 /**
444 * @return array|null
445 */
446 private function getNewsfeedDataForJs()
447 {
448 try {
449 /** @var NewsfeedProvider $provider */
450 $provider = WPStaging::make(NewsfeedProvider::class);
451 return $provider->getNewsfeedData();
452 } catch (\Exception $e) {
453 return null;
454 }
455 }
456
457 /**
458 * Whether this is a brand-new install that has never been upgraded from a
459 * previous version. The "what's new" modal is meant to inform existing users
460 * what an update brings, so it must not greet new users on their first visit.
461 *
462 * The "upgraded from" option is empty on a fresh install and holds the prior
463 * version once a real upgrade has happened, which cleanly tells the two apart.
464 *
465 * @return bool
466 */
467 private function isNewUser(): bool
468 {
469 $upgradedFromOption = WPStaging::isPro() ? 'wpstgpro_version_upgraded_from' : 'wpstg_version_upgraded_from';
470
471 return empty(get_option($upgradedFromOption, ''));
472 }
473
474 /**
475 * @return bool
476 */
477 private function isValidProLicense(): bool
478 {
479 if (!class_exists('\WPStaging\Pro\License\Licensing')) {
480 return false;
481 }
482
483 try {
484 return WPStaging::make(\WPStaging\Pro\License\Licensing::class)->isRegisteredLicense();
485 } catch (\Exception $e) {
486 return false;
487 }
488 }
489
490 /**
491 * @return string
492 */
493 private function getLicenseUpgradeUrl(): string
494 {
495 if (!WPStaging::isPro() || !class_exists('\WPStaging\Pro\License\Licensing')) {
496 return '';
497 }
498
499 try {
500 /** @var \WPStaging\Pro\License\Licensing $licensing */
501 $licensing = WPStaging::make(\WPStaging\Pro\License\Licensing::class);
502 return $licensing->getUpgradeToDevUrl();
503 } catch (\Exception $e) {
504 return '';
505 }
506 }
507
508 /**
509 * @return string
510 */
511 private function getLicenseRenewalUrl(): string
512 {
513 if (!WPStaging::isPro() || !class_exists('\WPStaging\Pro\License\Licensing')) {
514 return '';
515 }
516
517 try {
518 $isExpired = WPStaging::make(CliIntegrationNotice::class)->isExpiredDeveloperOrHigherLicense();
519 if (!$isExpired) {
520 return '';
521 }
522
523 $licenseKey = trim(get_option(\WPStaging\Pro\License\Licensing::WPSTG_LICENSE_KEY, ''));
524 return Language::localizeCheckoutUrl('https://wp-staging.com/checkout/?nocache=true&edd_license_key=' . urlencode($licenseKey) . '&download_id=11');
525 } catch (\Exception $e) {
526 return '';
527 }
528 }
529
530 /**
531 * Get the script loading args for wp_enqueue_script's 5th parameter.
532 * On WP 6.5+: uses defer strategy (loads in head, downloads in parallel, executes after parsing).
533 * On older WP: loads in footer as fallback to avoid render-blocking.
534 *
535 * @return array|bool
536 */
537 public function getScriptLoadingStrategy()
538 {
539 if (function_exists('wp_register_script_module')) {
540 return ['strategy' => 'defer', 'in_footer' => false];
541 }
542
543 return true;
544 }
545
546 /**
547 * Check given slug is not WP Staging admin page
548 *
549 * @param string $slug slug of the current page
550 *
551 * @return bool
552 */
553 private function isNotWPStagingAdminPage($slug)
554 {
555 if (WPStaging::isPro() || WPStaging::isDevBasic()) {
556 $availableSlugs = [
557 "toplevel_page_wpstg_clone",
558 "toplevel_page_wpstg_backup",
559 "wp-staging-pro_page_wpstg_clone",
560 "wp-staging-pro_page_wpstg_backup",
561 "wp-staging-pro_page_wpstg-settings",
562 "wp-staging-pro_page_wpstg-tools",
563 "wp-staging-pro_page_wpstg-license",
564 "wp-staging-pro_page_wpstg-restorer",
565 // DevBasic mode uses the basic dist plugin (wp-staging/) with WPSTG_DEV_BASIC constant,
566 // so WordPress generates wp-staging_page_* slugs instead of wp-staging-pro_page_*
567 "wp-staging_page_wpstg_clone",
568 "wp-staging_page_wpstg_backup",
569 "wp-staging_page_wpstg-settings",
570 "wp-staging_page_wpstg-tools",
571 ];
572 } else {
573 $availableSlugs = [
574 "toplevel_page_wpstg_clone",
575 "toplevel_page_wpstg_backup",
576 "wp-staging_page_wpstg_clone",
577 "wp-staging_page_wpstg_backup",
578 "wp-staging_page_wpstg-settings",
579 "wp-staging_page_wpstg-tools",
580 "wp-staging_page_wpstg-welcome",
581 ];
582 }
583
584 return !in_array($slug, $availableSlugs);
585 }
586
587 /**
588 * Remove heartbeat api and user login check
589 *
590 * @action admin_enqueue_scripts 100 1
591 * @see AssetServiceProvider.php
592 *
593 * @param string $hook
594 */
595 public function removeWPCoreJs($hook)
596 {
597 if ($this->isNotWPStagingAdminPage($hook)) {
598 return;
599 }
600
601 // Disable user login status check
602 // Todo: Can we remove this now that we have AccessToken?
603 remove_action('admin_enqueue_scripts', 'wp_auth_check_load');
604
605 // Disable heartbeat check for cloning and pushing
606 wp_deregister_script('heartbeat');
607 }
608
609 /**
610 * Check if current page is plugins.php
611 * @global array $pagenow
612 * @return bool
613 */
614 private function isPluginsPage()
615 {
616 global $pagenow;
617
618 return ($pagenow === 'plugins.php');
619 }
620
621 /**
622 * @return string
623 */
624 public function getStagingAdminBarColor()
625 {
626 $barColor = $this->settings->getAdminBarColor();
627 if (!preg_match("/#([a-f0-9]{3}){1,2}\b/i", $barColor)) {
628 $barColor = self::DEFAULT_ADMIN_BAR_BG;
629 }
630
631 return "#wpadminbar { background-color: {$barColor} !important; }";
632 }
633
634 /**
635 * Check whether app is in debug mode or in dev mode
636 *
637 * @return bool
638 */
639 private function isDebugOrDevMode()
640 {
641 return ($this->settings->isDebugMode() || (defined('WPSTG_IS_DEV') && WPSTG_IS_DEV === true) || (defined('WPSTG_DEBUG') && WPSTG_DEBUG === true));
642 }
643
644 /**
645 * Change admin_bar site_name
646 *
647 * @return void
648 * @global object $wp_admin_bar
649 */
650 public function changeSiteName()
651 {
652 if (!(new SiteInfo())->isStagingSite()) {
653 return;
654 }
655
656 global $wp_admin_bar;
657 $blogName = get_bloginfo('name');
658 if (empty($blogName)) {
659 $siteUrl = get_site_url();
660 $parsedUrl = parse_url($siteUrl);
661 $blogName = $parsedUrl['host'];
662 }
663
664 $siteTitle = Hooks::applyFilters(self::FILTER_STAGING_SITE_TITLE, 'STAGING');
665 $title = (strlen($blogName) > 20) ? substr($blogName, 0, 20) . '...' : $blogName;
666 $wp_admin_bar->add_menu(
667 [
668 'id' => 'site-name',
669 'title' => $siteTitle . ' - ' . $title,
670 'href' => is_admin() ? home_url('/') : admin_url(),
671 ]
672 );
673 }
674
675 /**
676 * @param string $hook
677 * @return void
678 */
679 public function dequeueNonWpstgElements($hook)
680 {
681 if ($this->isNotWPStagingAdminPage($hook)) {
682 return;
683 }
684
685 $stylesToRemove = ['wp-reset-sweetalert2'];
686 $scriptsToRemove = [
687 'wp-reset-sweetalert2',
688 'wp-reset',
689 ];
690
691 foreach ($stylesToRemove as $style) {
692 wp_dequeue_style($style);
693 }
694
695 foreach ($scriptsToRemove as $script) {
696 wp_dequeue_script($script);
697 }
698 }
699
700 /**
701 * @param string $iconName
702 * @param string $class
703 * @return void
704 */
705 public function renderSvg(string $iconName, string $class = '')
706 {
707 $fullPath = WPSTG_PLUGIN_DIR . '/assets/svg/' . $iconName . '.svg';
708 if (!file_exists($fullPath)) {
709 return;
710 }
711
712 $svgCode = file_get_contents($fullPath);
713 $svgCode = preg_replace('/<svg(.*?)>/', '<svg$1 class="' . $class . '">', $svgCode);
714 echo Escape::escapeHtml($svgCode);
715 }
716
717
718 private function getRestUrl(): string
719 {
720 $restUrl = get_transient(self::TRANSIENT_REST_URL);
721 if ($restUrl) {
722 return $restUrl;
723 }
724
725 $restUrl = get_rest_url(null, Rest::WPSTG_ROUTE_NAMESPACE_V1);
726 if (!$this->isWorkingTestUrl($restUrl)) {
727 $restUrl = site_url('/?rest_route=/' . Rest::WPSTG_ROUTE_NAMESPACE_V1);
728 }
729
730 set_transient(self::TRANSIENT_REST_URL, $restUrl, 24 * HOUR_IN_SECONDS);
731
732 return $restUrl;
733 }
734
735 private function isWorkingTestUrl($url)
736 {
737 $url .= '/ping&accessToken=' . $this->accessToken->getToken();
738 $response = wp_remote_request($url, [
739 'method' => 'GET',
740 'timeout' => 5,
741 'sslverify' => false,
742 'headers' => [
743 'Accept' => 'application/json',
744 ],
745 ]);
746
747 if (is_wp_error($response)) {
748 return false;
749 }
750
751 $code = wp_remote_retrieve_response_code($response);
752 if ($code !== 200) {
753 return false;
754 }
755
756 return true;
757 }
758 }
759