| @@ -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']); |
| @@ -946,12 +963,30 @@ | ||
| 946 | 963 | |
| 947 | 964 | function save_settings() |
| 948 | 965 | { |
| 949 | 966 | |
| 950 | - if (!empty($_GET['page']) && $_GET['page'] == 'berqwp' && isset($_GET['activate-free'])) { | |
| 967 | + if (current_user_can('manage_options') && !empty($_GET['page']) && $_GET['page'] == 'berqwp' && isset($_GET['activate-free'])) { | |
| 951 | 968 | $berqconfigs = berqConfigs::getInstance(); |
| 952 | - $berqconfigs->update_configs(['optimization_method' => 'local']); | |
| 969 | + $configs = $berqconfigs->get_configs(); | |
| 970 | + $site_id = $configs['site_id']; | |
| 953 | 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 | + | |
| 954 | 989 | $location = get_admin_url() . 'admin.php?page=berqwp'; |
| 955 | 990 | wp_safe_redirect($location); |
| 956 | 991 | exit; |
| 957 | 992 | } |
| @@ -1501,8 +1536,162 @@ | ||
| 1501 | 1536 | return array_diff($plugins, array('wpemoji')); |
| 1502 | 1537 | } else { |
| 1503 | 1538 | return array(); |
| 1504 | 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()); | |
| 1505 | 1694 | } |
| 1506 | 1695 | |
| 1507 | 1696 | // function clear_cache(WP_REST_Request $request) |
| 1508 | 1697 | // { |