'', 'key' => '', 'enabled' => true]); } /** * Read the script address and project key out of whatever the user pasted: the full install line from * Scribelo's Share & install tab, or just the pk_ key. Anything else is rejected rather than printed. */ function scribelo_parse_install_code(string $code): ?array { $code = trim(wp_unslash($code)); if (preg_match('/^pk_[A-Za-z0-9_-]{8,}$/', $code)) { return ['src' => 'https://scribelo.io/snippet.js', 'key' => $code]; } if (!preg_match('/\bsrc\s*=\s*["\']([^"\']+)["\']/i', $code, $src) || !preg_match('/\bdata-project\s*=\s*["\'](pk_[A-Za-z0-9_-]{8,})["\']/i', $code, $key)) { return null; } $url = esc_url_raw($src[1], ['https', 'http']); $path = (string) wp_parse_url($url, PHP_URL_PATH); if ($url === '' || substr($path, -strlen('/snippet.js')) !== '/snippet.js') { return null; } return ['src' => $url, 'key' => $key[1]]; } // ---------------------------------------------------------------- front end add_action('wp_enqueue_scripts', function () { $s = scribelo_settings(); if (!$s['enabled'] || $s['src'] === '' || $s['key'] === '') { return; } // The script does nothing for normal visitors; it only wakes up when opened from a Scribelo review link. // No version is added to the address: the script is served by Scribelo and kept up to date there. wp_enqueue_script('scribelo-review', $s['src'], [], null, true); // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion }); /** * Add the project key and async to the script tag. The data-* flags ask speed-optimisation tools (LiteSpeed, * Cloudflare Rocket Loader, WP Rocket, Jetpack Boost…) not to delay, defer or merge it: it has to run as soon * as the review screen opens the page. */ add_filter('script_loader_tag', function ($tag, $handle) { if ($handle !== 'scribelo-review') { return $tag; } $attrs = ' data-project="' . esc_attr(scribelo_settings()['key']) . '" async data-no-optimize="1" data-no-defer="1" data-no-minify="1" data-cfasync="false" data-jetpack-boost="ignore"'; return preg_replace('/ do_action('litespeed_purge_all')); } if (function_exists('sg_cachepress_purge_cache')) { $try('SiteGround Optimizer', 'sg_cachepress_purge_cache'); } if (isset($GLOBALS['wp_fastest_cache']) && method_exists($GLOBALS['wp_fastest_cache'], 'deleteCache')) { $try('WP Fastest Cache', fn () => $GLOBALS['wp_fastest_cache']->deleteCache(true)); } if (class_exists('autoptimizeCache')) { $try('Autoptimize', ['autoptimizeCache', 'clearall']); } if (class_exists('Cache_Enabler')) { $try('Cache Enabler', fn () => do_action('cache_enabler_clear_complete_cache')); } if (class_exists('Breeze_PurgeCache')) { $try('Breeze', ['Breeze_PurgeCache', 'breeze_cache_flush']); } if (defined('WPHB_VERSION')) { $try('Hummingbird', fn () => do_action('wphb_clear_page_cache')); } if (defined('NGINX_HELPER_BASENAME')) { $try('Nginx Helper', fn () => do_action('rt_nginx_helper_purge_all')); } return $cleared; } // ---------------------------------------------------------------- settings page add_action('admin_menu', function () { add_options_page(__('Scribelo', 'scribelo'), __('Scribelo', 'scribelo'), 'manage_options', 'scribelo', 'scribelo_settings_page'); }); add_filter('plugin_action_links_' . plugin_basename(__FILE__), function (array $links): array { array_unshift($links, '' . esc_html__('Settings', 'scribelo') . ''); return $links; }); add_action('admin_post_scribelo_save', function () { if (!current_user_can('manage_options')) { wp_die(esc_html__('You are not allowed to change these settings.', 'scribelo')); } check_admin_referer('scribelo_save'); $s = scribelo_settings(); $s['enabled'] = !empty($_POST['scribelo_enabled']); // Not sanitised here because sanitising would strip the