| @@ -132,8 +132,25 @@ | ||
| 132 | 132 | |
| 133 | 133 | // Sync addons from cloud |
| 134 | 134 | add_action('init', [$this, 'sync_addons']); |
| 135 | 135 | |
| 136 | + // Debloat: WordPress feature toggles | |
| 137 | + if (get_option('berqwp_disable_emojis')) { | |
| 138 | + add_action('init', [$this, 'disable_emoji']); | |
| 139 | + } | |
| 140 | + add_action('init', [$this, 'apply_heartbeat_settings'], 1); | |
| 141 | + add_action('init', [$this, 'apply_debloat_settings'], 1); | |
| 142 | + | |
| 143 | + // Database: manual cleanup AJAX actions | |
| 144 | + add_action('wp_ajax_berqwp_db_run_action', [$this, 'ajax_db_run_action']); | |
| 145 | + | |
| 146 | + // Database: scheduled optimization via WP-Cron | |
| 147 | + add_filter('cron_schedules', [$this, 'add_monthly_cron_schedule']); | |
| 148 | + add_action('berqwp_db_scheduled_optimize', [$this, 'run_scheduled_db_optimize']); | |
| 149 | + add_action('berqwp_reschedule_db_cron', [$this, 'reschedule_db_cron']); | |
| 150 | + add_action('berqwp_activate_plugin', [$this, 'reschedule_db_cron']); | |
| 151 | + add_action('berqwp_deactivate_plugin', [$this, 'clear_db_cron']); | |
| 152 | + | |
| 136 | 153 | // Multisite support |
| 137 | 154 | if (function_exists('is_multisite') && is_multisite()) { |
| 138 | 155 | add_action('network_admin_menu', [$this, 'register_network_menu']); |
| 139 | 156 | add_action('network_admin_edit_berqwp_network_save', [$this, 'save_network_settings']); |
| @@ -153,8 +170,24 @@ | ||
| 153 | 170 | |
| 154 | 171 | return self::$instance; |
| 155 | 172 | } |
| 156 | 173 | |
| 174 | + function upgrade_notice() { | |
| 175 | + | |
| 176 | + if (!berqwp_can_use_cloud()) { | |
| 177 | + return; | |
| 178 | + } | |
| 179 | + | |
| 180 | + if (empty($this->key_response->product_ref)) { | |
| 181 | + return; | |
| 182 | + } | |
| 183 | + | |
| 184 | + if ($this->key_response->product_ref == 'Free Account' && bwp_cached_pages_count() >= 10) { | |
| 185 | + | |
| 186 | + bwp_notice('warning', 'Free Plan Limit Reached', "<p>You've reached the limit of 10 optimized pages for your free BerqWP account. Upgrade now to optimize unlimited pages and get the best performance for your entire site!</p>"); | |
| 187 | + } | |
| 188 | + } | |
| 189 | + | |
| 157 | 190 | function switch_optimization_method() { |
| 158 | 191 | // Check if the user has the necessary nonce and the action matches |
| 159 | 192 | if (isset($_GET['action']) && $_GET['action'] === 'switch_optimization_method_local' && wp_verify_nonce(sanitize_text_field(wp_unslash($_GET['_wpnonce'] ?? '')), 'switch_optimization_method_local_action')) { |
| 160 | 193 | |
| @@ -161,8 +194,11 @@ | ||
| 161 | 194 | |
| 162 | 195 | $berqconfigs = berqConfigs::getInstance(); |
| 163 | 196 | $berqconfigs->update_configs(['optimization_method' => 'local']); |
| 164 | 197 | |
| 198 | + // Require flush cache | |
| 199 | + update_option('bwp_require_flush_cache', 1); | |
| 200 | + | |
| 165 | 201 | $redirect_url = wp_get_referer(); |
| 166 | 202 | |
| 167 | 203 | // Redirect back to the referring page after clearing the cache |
| 168 | 204 | wp_safe_redirect($redirect_url); |
| @@ -179,8 +215,10 @@ | ||
| 179 | 215 | } else { |
| 180 | 216 | $berqconfigs->update_configs(['optimization_method' => 'cloud']); |
| 181 | 217 | } |
| 182 | 218 | |
| 219 | + // Require flush cache | |
| 220 | + update_option('bwp_require_flush_cache', 1); | |
| 183 | 221 | |
| 184 | 222 | $redirect_url = wp_get_referer(); |
| 185 | 223 | |
| 186 | 224 | // Redirect back to the referring page after clearing the cache |
| @@ -924,8 +962,36 @@ | ||
| 924 | 962 | } |
| 925 | 963 | |
| 926 | 964 | function save_settings() |
| 927 | 965 | { |
| 966 | + | |
| 967 | + if (current_user_can('manage_options') && !empty($_GET['page']) && $_GET['page'] == 'berqwp' && isset($_GET['activate-free'])) { | |
| 968 | + $berqconfigs = berqConfigs::getInstance(); | |
| 969 | + $configs = $berqconfigs->get_configs(); | |
| 970 | + $site_id = $configs['site_id']; | |
| 971 | + | |
| 972 | + if (empty($site_id)) { | |
| 973 | + $site_id = berqwp_generate_site_id(); | |
| 974 | + } | |
| 975 | + | |
| 976 | + $berqconfigs->update_configs([ | |
| 977 | + 'site_id' => $site_id, | |
| 978 | + 'optimization_method' => 'local' | |
| 979 | + ]); | |
| 980 | + | |
| 981 | + wp_remote_post(BerqWPCloud::$endpoint."free-user", [ | |
| 982 | + 'timeout' => 30, | |
| 983 | + 'body' => [ | |
| 984 | + 'site_id' => $site_id, | |
| 985 | + 'site_url' => get_option('home'), | |
| 986 | + ] | |
| 987 | + ]); | |
| 988 | + | |
| 989 | + $location = get_admin_url() . 'admin.php?page=berqwp'; | |
| 990 | + wp_safe_redirect($location); | |
| 991 | + exit; | |
| 992 | + } | |
| 993 | + | |
| 928 | 994 | require_once optifer_PATH . '/admin/save-settings.php'; |
| 929 | 995 | } |
| 930 | 996 | |
| 931 | 997 | function notices() |
| @@ -932,8 +998,10 @@ | ||
| 932 | 998 | { |
| 933 | 999 | |
| 934 | 1000 | $plugin_name = defined('BERQWP_PLUGIN_NAME') ? BERQWP_PLUGIN_NAME : 'BerqWP'; |
| 935 | 1001 | |
| 1002 | + $this->upgrade_notice(); | |
| 1003 | + | |
| 936 | 1004 | if (isset($_GET['berqwp_page_compression_enabled'])) { |
| 937 | 1005 | bwp_notice('success', 'Page Compression Enabled', "<p>Page compression has been successfully enabled on your website.</p>"); |
| 938 | 1006 | } |
| 939 | 1007 | |
| @@ -987,9 +1055,13 @@ | ||
| 987 | 1055 | // if (file_exists($adv_cache_path) && !is_writable($adv_cache_path)) { |
| 988 | 1056 | // bwp_notice('warning', 'advanced-cache.php is not writable', "<p>$plugin_name can't write to wp-content/advanced-cache.php — please check file permissions or re-save settings to regenerate it.</p>", []); |
| 989 | 1057 | // } |
| 990 | 1058 | |
| 991 | - if (!get_transient('bwp_hide_feedback_notice') && !get_option('bwp_quit_feedback') && bwp_show_account()) { | |
| 1059 | + $berqconfigs = berqConfigs::getInstance(); | |
| 1060 | + $configs = $berqconfigs->get_configs(); | |
| 1061 | + $readyForCache = !empty($configs['optimization_method']); | |
| 1062 | + | |
| 1063 | + if ($readyForCache && bwp_is_home_cached() && !get_transient('bwp_hide_feedback_notice') && !get_option('bwp_quit_feedback') && bwp_show_account()) { | |
| 992 | 1064 | bwp_notice('info bwp_feedback', 'Loving BerqWP\'s performance?', '<p>Show some love and help us grow 👉 - <a href="https://wordpress.org/support/plugin/searchpro/reviews/#new-post" target="_blank">Rate BerqWP Plugin</a>. Your insights shape our journey.</p>', [ |
| 993 | 1065 | [ |
| 994 | 1066 | 'href' => 'https://wordpress.org/support/plugin/searchpro/reviews/#new-post', |
| 995 | 1067 | 'text' => '❤️ You deserve it', |
| @@ -997,9 +1069,9 @@ | ||
| 997 | 1069 | 'target' => '_blank', |
| 998 | 1070 | ], |
| 999 | 1071 | [ |
| 1000 | 1072 | 'href' => get_admin_url() . 'admin.php?page=berqwp&bwp_quit_feedback', |
| 1001 | - 'text' => '👍 Already did', | |
| 1073 | + 'text' => '👍 Already done', | |
| 1002 | 1074 | 'classes' => '', |
| 1003 | 1075 | 'target' => '', |
| 1004 | 1076 | ], |
| 1005 | 1077 | [ |
| @@ -1057,16 +1129,26 @@ | ||
| 1057 | 1129 | delete_transient('berq_force_cache_notice'); |
| 1058 | 1130 | bwp_notice('success', '', "<p>The cache for page ($forced_page) has been queued with high priority and will be generated soon.</p>", []); |
| 1059 | 1131 | } |
| 1060 | 1132 | |
| 1061 | - if (get_option('bwp_require_flush_cache', false)) { | |
| 1062 | - bwp_notice('warning', 'Cache Flush Required', '<p>To apply the changes, please flush the cache.</p>', [ | |
| 1133 | + if ($readyForCache && get_option('bwp_require_flush_cache', false)) { | |
| 1134 | + $cache_rebuild_btns = [ | |
| 1063 | 1135 | [ |
| 1064 | 1136 | 'href' => esc_attr(wp_nonce_url(admin_url('admin-post.php?action=clear_cache'), 'clear_cache_action')), |
| 1065 | 1137 | 'text' => 'Flush cache', |
| 1066 | 1138 | 'classes' => '', |
| 1067 | 1139 | ] |
| 1068 | - ]); | |
| 1140 | + ]; | |
| 1141 | + | |
| 1142 | + if (berqwp_can_use_cloud()) { | |
| 1143 | + $cache_rebuild_btns[] = [ | |
| 1144 | + 'href' => esc_attr(wp_nonce_url(admin_url('admin-post.php?action=warmup_cache'), 'warmup_cache_action')), | |
| 1145 | + 'text' => 'Warmup cache', | |
| 1146 | + 'classes' => '', | |
| 1147 | + ]; | |
| 1148 | + } | |
| 1149 | + | |
| 1150 | + bwp_notice('warning', 'Cache Flush Required', '<p>To apply the changes, please flush the cache.</p>', $cache_rebuild_btns); | |
| 1069 | 1151 | } |
| 1070 | 1152 | |
| 1071 | 1153 | if (berq_is_localhost() && berqwp_can_use_cloud()) { |
| 1072 | 1154 | bwp_notice('warning', 'Localhost environment detected:', "<p>$plugin_name requires a live, publicly accessible website to function.</p>", []); |
| @@ -1180,9 +1262,9 @@ | ||
| 1180 | 1262 | 'body' => $body |
| 1181 | 1263 | ]); |
| 1182 | 1264 | |
| 1183 | 1265 | if (is_wp_error($lic_response)) { |
| 1184 | - $berq_log->info("Couldn't reach BerqWP server."); | |
| 1266 | + $berq_log->info("Couldn't reach BerqWP server.".print_r($lic_response, true)); | |
| 1185 | 1267 | return; |
| 1186 | 1268 | } |
| 1187 | 1269 | |
| 1188 | 1270 | $lic_body = wp_remote_retrieve_body($lic_response); |
| @@ -1454,8 +1536,162 @@ | ||
| 1454 | 1536 | return array_diff($plugins, array('wpemoji')); |
| 1455 | 1537 | } else { |
| 1456 | 1538 | return array(); |
| 1457 | 1539 | } |
| 1540 | + } | |
| 1541 | + | |
| 1542 | + // Apply the selected Heartbeat API mode (default / restrict / throttle / disable) | |
| 1543 | + function apply_heartbeat_settings() | |
| 1544 | + { | |
| 1545 | + $mode = get_option('berqwp_heartbeat_mode', 'default'); | |
| 1546 | + | |
| 1547 | + if ($mode === 'default') { | |
| 1548 | + return; | |
| 1549 | + } | |
| 1550 | + | |
| 1551 | + if ($mode === 'disable') { | |
| 1552 | + wp_deregister_script('heartbeat'); | |
| 1553 | + return; | |
| 1554 | + } | |
| 1555 | + | |
| 1556 | + if ($mode === 'restrict') { | |
| 1557 | + global $pagenow; | |
| 1558 | + if (!in_array($pagenow, ['post.php', 'post-new.php'], true)) { | |
| 1559 | + wp_deregister_script('heartbeat'); | |
| 1560 | + } | |
| 1561 | + return; | |
| 1562 | + } | |
| 1563 | + | |
| 1564 | + if ($mode === 'throttle') { | |
| 1565 | + add_filter('heartbeat_settings', [$this, 'throttle_heartbeat_interval']); | |
| 1566 | + } | |
| 1567 | + } | |
| 1568 | + | |
| 1569 | + // Filter callback: clamp Heartbeat interval to the configured value | |
| 1570 | + function throttle_heartbeat_interval($settings) | |
| 1571 | + { | |
| 1572 | + $settings['interval'] = max(15, min(300, (int) get_option('berqwp_heartbeat_interval', 60))); | |
| 1573 | + return $settings; | |
| 1574 | + } | |
| 1575 | + | |
| 1576 | + // Apply the remaining Debloat toggles (embeds, XML-RPC, REST head links, head meta, self pingbacks) | |
| 1577 | + function apply_debloat_settings() | |
| 1578 | + { | |
| 1579 | + if (get_option('berqwp_disable_embeds')) { | |
| 1580 | + add_action('wp_footer', [$this, 'deregister_embed_script']); | |
| 1581 | + remove_action('wp_head', 'wp_oembed_add_discovery_links'); | |
| 1582 | + remove_action('wp_head', 'wp_oembed_add_host_js'); | |
| 1583 | + add_filter('embed_oembed_discover', '__return_false'); | |
| 1584 | + } | |
| 1585 | + | |
| 1586 | + if (get_option('berqwp_disable_xmlrpc')) { | |
| 1587 | + add_filter('xmlrpc_enabled', '__return_false'); | |
| 1588 | + } | |
| 1589 | + | |
| 1590 | + if (get_option('berqwp_remove_rest_head_links')) { | |
| 1591 | + remove_action('wp_head', 'rest_output_link_wp_head'); | |
| 1592 | + remove_action('template_redirect', 'rest_output_link_header', 11); | |
| 1593 | + } | |
| 1594 | + | |
| 1595 | + if (get_option('berqwp_remove_head_meta')) { | |
| 1596 | + remove_action('wp_head', 'rsd_link'); | |
| 1597 | + remove_action('wp_head', 'wlwmanifest_link'); | |
| 1598 | + remove_action('wp_head', 'wp_shortlink_wp_head'); | |
| 1599 | + remove_action('wp_head', 'wp_generator'); | |
| 1600 | + } | |
| 1601 | + | |
| 1602 | + if (get_option('berqwp_disable_self_pingbacks')) { | |
| 1603 | + add_action('pre_ping', [$this, 'remove_self_pingbacks']); | |
| 1604 | + } | |
| 1605 | + } | |
| 1606 | + | |
| 1607 | + // Callback: deregister the embed.min.js frontend script | |
| 1608 | + function deregister_embed_script() | |
| 1609 | + { | |
| 1610 | + wp_deregister_script('wp-embed'); | |
| 1611 | + } | |
| 1612 | + | |
| 1613 | + // Callback: strip links pointing back to this site from the pingback target list | |
| 1614 | + function remove_self_pingbacks(&$links) | |
| 1615 | + { | |
| 1616 | + $home = get_option('home'); | |
| 1617 | + foreach ($links as $key => $link) { | |
| 1618 | + if (strpos($link, (string) $home) === 0) { | |
| 1619 | + unset($links[$key]); | |
| 1620 | + } | |
| 1621 | + } | |
| 1622 | + } | |
| 1623 | + | |
| 1624 | + // AJAX: run a single Database tab cleanup action on demand | |
| 1625 | + function ajax_db_run_action() | |
| 1626 | + { | |
| 1627 | + check_ajax_referer('wp_rest', 'nonce'); | |
| 1628 | + | |
| 1629 | + if (!current_user_can('manage_options')) { | |
| 1630 | + wp_send_json_error(['message' => __('Permission denied.', 'searchpro')]); | |
| 1631 | + } | |
| 1632 | + | |
| 1633 | + $task = isset($_POST['task']) ? sanitize_text_field($_POST['task']) : ''; | |
| 1634 | + $limit = isset($_POST['limit']) ? max(0, (int) $_POST['limit']) : (int) get_option('berqwp_db_revision_limit', 5); | |
| 1635 | + | |
| 1636 | + $result = berqDatabase::run_task($task, ['limit' => $limit]); | |
| 1637 | + | |
| 1638 | + if ($result === false) { | |
| 1639 | + wp_send_json_error(['message' => __('Unknown cleanup task.', 'searchpro')]); | |
| 1640 | + } | |
| 1641 | + | |
| 1642 | + wp_send_json_success($result); | |
| 1643 | + } | |
| 1644 | + | |
| 1645 | + // Register a "once monthly" WP-Cron interval (core only ships hourly/twicedaily/daily) | |
| 1646 | + function add_monthly_cron_schedule($schedules) | |
| 1647 | + { | |
| 1648 | + $schedules['berqwp_monthly'] = [ | |
| 1649 | + 'interval' => 30 * DAY_IN_SECONDS, | |
| 1650 | + 'display' => __('Once Monthly', 'searchpro'), | |
| 1651 | + ]; | |
| 1652 | + return $schedules; | |
| 1653 | + } | |
| 1654 | + | |
| 1655 | + // (Re)schedule the Database tab's recurring optimization cron event based on current settings | |
| 1656 | + function reschedule_db_cron() | |
| 1657 | + { | |
| 1658 | + wp_clear_scheduled_hook('berqwp_db_scheduled_optimize'); | |
| 1659 | + | |
| 1660 | + if (!get_option('berqwp_db_schedule_enabled')) { | |
| 1661 | + return; | |
| 1662 | + } | |
| 1663 | + | |
| 1664 | + $frequency = get_option('berqwp_db_schedule_frequency', 'weekly'); | |
| 1665 | + $recurrence = 'weekly'; | |
| 1666 | + if ($frequency === 'daily') { | |
| 1667 | + $recurrence = 'daily'; | |
| 1668 | + } elseif ($frequency === 'monthly') { | |
| 1669 | + $recurrence = 'berqwp_monthly'; | |
| 1670 | + } | |
| 1671 | + | |
| 1672 | + if (!wp_next_scheduled('berqwp_db_scheduled_optimize')) { | |
| 1673 | + wp_schedule_event(time(), $recurrence, 'berqwp_db_scheduled_optimize'); | |
| 1674 | + } | |
| 1675 | + } | |
| 1676 | + | |
| 1677 | + // Clear the Database tab's cron event (called on plugin deactivation) | |
| 1678 | + function clear_db_cron() | |
| 1679 | + { | |
| 1680 | + wp_clear_scheduled_hook('berqwp_db_scheduled_optimize'); | |
| 1681 | + } | |
| 1682 | + | |
| 1683 | + // WP-Cron callback: run every scheduled task and record the run timestamp | |
| 1684 | + function run_scheduled_db_optimize() | |
| 1685 | + { | |
| 1686 | + $tasks = get_option('berqwp_db_scheduled_tasks', []); | |
| 1687 | + $limit = (int) get_option('berqwp_db_revision_limit', 5); | |
| 1688 | + | |
| 1689 | + foreach ((array) $tasks as $task) { | |
| 1690 | + berqDatabase::run_task($task, ['limit' => $limit]); | |
| 1691 | + } | |
| 1692 | + | |
| 1693 | + update_option('berqwp_db_optimize_last_run', time()); | |
| 1458 | 1694 | } |
| 1459 | 1695 | |
| 1460 | 1696 | // function clear_cache(WP_REST_Request $request) |
| 1461 | 1697 | // { |